实时分析的真相:Snowflake vs. ClickHouse Cloud,谁是端到端王者?
本文字数:19026;估计阅读时间:48 分钟
作者:Tom Schreiber, Mark Needham and Lionel Palacin
TL;DR
实时分析的基准测试需要端到端地衡量系统:包括新数据摄入、查询就绪数据的维护、快速响应查询,以及维持整个路径运行的成本。
这正是 CostBench 所衡量的。它综合评估了持续摄入、数据维护和查询执行的成本与延迟,因为不同的系统在工作分配上有所侧重。
对静态数据集进行的只读基准测试,可以展示数据准备就绪后查询的返回速度。但它无法揭示将数据转化为查询就绪状态的成本,也无法评估在新数据持续到达并并行维护的同时,查询能否保持快速响应。
在本文中,我们将使用 CostBench 来比较 Snowflake 和 ClickHouse Cloud 在完整的实时分析路径上的表现。
想观看视频演示?
本次网络研讨会将以视频形式呈现相同的基准测试内容,并深入探讨结果背后的机制:包括端到端路径的成本性能、持续变化的数据,以及 ClickHouse 为何能够在数据摄入时即达到查询就绪状态,以及物化视图如何与基表保持同步。
查看媒体链接:https://www.youtube.com/watch?v=_b-FD39YF5A&t=3s
实时分析并非从查询运行开始
实时分析始于新数据的到达。
在仪表板、用户或 AI 代理获得快速响应之前,系统已经完成了大量工作:包括摄入新行、对数据进行组织以方便剪枝、维护派生表、确保数据新鲜度,并保持读取容量以支持低延迟查询。
CostBench 旨在衡量的就是这条完整路径:它衡量的不仅是最终的读取查询,而是将新数据转化为快速响应的整个运行系统。
这也是我们 之前关于查询就绪数据的基准测试 的核心思想。我们衡量了这条路径的一个重要方面:即持续摄入数据并对原始数据进行物理组织以支持快速分析读取的成本效益。
Snowflake 对该基准测试做出了回应,提出了一系列建议,包括:使用不同的摄取方法、使用更大的数据仓库进行加载操作,以及在可用时使用 Snowflake 更新的实时功能。
其中一些建议旨在改进 Snowflake 的设置。另一些则关注不同的问题,例如,当目标是最大吞吐量而非持续查询就绪性时,Snowflake 批量加载数据的速度如何。但所有这些都殊途同归,指向我们最初秉持的同一原则:
实时分析系统应作为一条完整路径进行基准测试,而非孤立地进行数据摄取、维护或读取测试。
这正是本文所做的工作。我们使用 CostBench 将该比较作为端到端基准测试重新运行,涵盖了:持续数据摄取 (continuous ingest)、原始数据组织 (raw-data organization)、预聚合数据新鲜度 (pre-aggregation freshness) 以及持续查询服务 (continuous query serving)。我们测试了两种 Snowflake 路径:广泛可用的标准表设置 (standard-table setup) 和更新的 Interactive Tables (交互式表) 设置。
所有基准测试代码和结果均可在 CostBench repository 获取。股票报价数据集需要 单独的数据许可,因此数据本身无法再分发。
CostBench 衡量完整的分析路径
加载静态数据集、多次运行每个查询并报告最快的热缓存 (hot-cache) 结果,并不能反映实时分析系统 (real-time analytics system) 的真实性能或成本。
大多数数据库基准测试仅加载一次静态数据集,让系统对其进行充分准备,然后多次运行每个查询并报告最快的热缓存结果。这种方式衡量的是对稳定且已准备好数据的重复读取性能。但它无法体现使新鲜数据达到查询就绪 (query-ready) 状态所需的时间和成本,也无法展现当查询持续运行在不断变化的数据之上时,它们的表现如何,尤其是在数据摄取、维护和刷新工作同时进行,且缓存视图从未稳定于单一静态状态的情况下。
这正是我们创建 CostBench 的初衷。
CostBench 从成本-性能角度衡量完整的分析路径,具体包括:
① 新鲜数据持续到达。
② 系统写入数据并使其达到 查询就绪 状态。
③ 原始数据以有序布局进行存储,以便后续查询能够跳过表的大部分内容,而非全表扫描。
④ 系统维护预聚合数据,从而使延迟最低的查询在执行时读取的数据量更小。
⑤ 最后,系统必须针对持续变化的数据,不间断地提供快速响应,同时后台的数据摄取、维护和刷新工作也必须持续进行。
CostBench 并非批量加载或回填基准测试CostBench 模拟了一个实时分析系统 (real-time analytics system),其中新数据在源端持续生成,并且必须在到达时立即可供查询 (query-ready)。它并非旨在衡量系统加载已有数据速度的批量加载 (bulk-load) 或回填 (backfill) 基准测试 (benchmark)。
在本文中,我们将这一方法应用于 Snowflake 和 ClickHouse。
我们的首次基准测试衡量了什么:立即可查询的原始数据
我们的 首次基准测试 衡量了完整 实时分析 路径中的一个重要环节:持续地将新写入的原始数据转化为立即可查询原始数据的成本。
下文将展示原始设置,并附带 Snowflake 提出的主要评论,这些评论有助于阐明一些问题。
① 数据集和排序键 (ordering key)
我们使用了 ClickBench 网络分析数据集,该数据集包含 100 多个列,并使用了 ClickBench 工作负载所用的原始多列排序键 (sorting key)。
这一选择是深思熟虑的。许多 ClickBench 查询得益于 ClickHouse 中的这种排序方式,因此为了确保后续查询性能测量的公平性,我们在 Snowflake 中使用了等效的聚簇键 (clustering key)。
Snowflake 的评论:使用一个更简单的聚簇键,并避免通过重复原始 ClickBench 数据集来达到千亿行数据量所带来的人为数据到达模式。
我们认为此评论是合理的,并将在下文的扩展基准测试中处理这两点。但实际上,它们回答了不同的问题:数据如何到达,以及系统需要为工作负载 (workload) 维护何种物理布局。
② 固定速率持续数据摄入
我们以每秒大约 100 万行(或每秒约 1 GB 未压缩数据)的速度持续摄入数据。
这并非一场旨在测试最大吞吐量的加载测试。我们有意将数据摄入速率固定,以模拟新数据持续不断抵达的实时工作负载。目标是使用最小、成本最低的 Snowflake 配置,使其在保持该速率的同时,确保数据表始终处于可查询状态。
Snowflake 的评论:建议使用 COPY INTO、Snowpipe Streaming、更大的数据仓库以及 Gen2 数据仓库。
这些对于其他数据摄入测试来说是合理的选择。然而,在本次基准测试中,加载机制并非重点。我们关注的并非 Snowflake 能多快完成 1000 亿行数据的加载,而是如何在常见的实时分析场景下,以固定的实时摄入速率持续处理数据所需的成本。
③ 查询就绪的原始数据,而非预聚合
首次基准测试主要关注基础表:即新写入的原始数据进入,并以查询就绪的原始数据形式输出。此次测试并未涵盖物化视图 (materialized views) 的性能。
Snowflake 的评论:更全面的生产环境设置应该涵盖数据管道的更多环节。
同意。这正是 CostBench 下一步将要增加的测试内容:在数据摄入和原始数据组织的同时,涵盖派生数据 (derived-data) 的维护、新鲜度以及读取。
④ 加载完成后测量读取
在数据表达到 1000 亿行后,我们运行了一次 ClickBench 查询工作负载,以验证其查询性能。
因此,首次基准测试并未衡量在数据摄入、集群、刷新或其他维护工作于后台持续进行时,系统所提供的持续服务能力。
Snowflake 的评论:建议使用 Interactive Tables 和 Interactive Warehouses 来实现高并发、低延迟的服务。
这一点很合理。在首次基准测试中,我们没有采用 Interactive Tables,因为该测试使用的是大多数客户实际能够使用的 Snowflake 方案:即带有集群的标准表。Interactive Tables 是一项较新的功能,目前仅在部分区域可用。
因此,在扩展基准测试中,我们将对两种方案进行测试:一是采用标准表和物化视图的广泛可用的 Snowflake 配置,二是在受支持区域内进行的 Interactive Tables 配置。
扩展基准测试旨在解决更广泛的问题
在 Snowflake 发布其回应之前,我们便已开始将新的 CostBench 方法应用于 一项更全面的全链路基准测试。
这次,我们特意从一个相对简单的场景入手:采用更简单的数据集和排序键,更清晰的数据写入模式,以及在数据持续更新的同时进行连续读取。这一设置规避了Snowflake在原始ClickBench测试中曾提出异议的多个因素。
稍后我们将使用更大的数据集重复此测试。但首先,我们希望在最理想的场景下,评估整个数据链路的性能。
① 更简单的数据集,时间戳有序写入
我们使用一个从数据提供商处获得授权的真实股票市场报价数据集,其中包含数百亿行数据。
与ClickBench相比,该数据集的结构要简单得多:它包含12列,一个由两列构成的简单排序键,并天然按照时间戳顺序排列。
我们以每秒100万行的稳定速率,严格按照时间戳顺序写入数据。按照这个速率,系统每28小时将接收到1000亿行新增数据。
② 简单聚簇键
这次,排序/聚簇键仅由两列组成:(sym, t)(即股票代码和时间戳)。这已是极致的自然和简洁。
ClickHouse 通过这些列对原始表进行排序,而 Snowflake 则通过这些列对原始表进行聚簇。
③ 包含预聚合
与原始基准测试不同,本次测试包含了持续维护的预聚合。
这意味着我们不仅衡量了持续有新数据写入的情况下,保持衍生数据实时更新所需的开销。
④ 针对对应数据布局的持续查询
本次测试中,查询操作在持续有新数据写入的同时不间断地进行。
该工作负载包含两种查询类型:一种是针对预聚合数据的仪表盘查询,另一种是针对原始数据且过滤器与原始表排序/聚簇键相匹配的下钻查询。
我们保持系统缓存开启。在涉及静态数据的基准测试中,我们通常会禁用查询结果缓存,以避免将内存查找的开销计入,而是专注于衡量纯粹的引擎性能。然而,在本场景中数据持续变化,因此缓存的效用大大降低;保持缓存开启能更好地反映实际使用场景。
我们每轮执行一次查询。这模拟了这些查询在实际中的使用方式:无论是仪表盘刷新、用户下钻,还是探索性的即席查询,都只针对数据的最新状态执行一次。
这更直接地模拟了实时场景:数据摄入、系统维护、数据新鲜度保障和数据读取所有操作都同时进行。
ClickHouse Cloud 设置
对于 ClickHouse Cloud,我们为数据摄入和读取分别使用了独立的服务,从而使写入路径和查询路径彼此隔离。
① 客户端设置
该客户端(基准测试驱动程序)被特意设计得非常简洁,它在 ClickHouse 和 Snowflake 上执行相同的工作。
它直接从现有的 Parquet 文件中以二进制形式读取 Parquet 行组,将这些行组组合成大小约为 100 万行的批次,并将这些批次发送到目标系统。客户端不进行任何解码、解压缩、编码和压缩操作。
这一点很重要,因为 Snowflake 在第一次基准测试的回应中指出,客户端成本是一个被忽略的因素。在此配置下,两个系统的客户端工作是相同的,并且只占用极少的 CPU 和内存资源,因此客户端成本不再是一个有意义的差异化因素。
② 摄入服务
数据摄入服务运行在专用的 ClickHouse Cloud 服务上,该服务由 2 个节点组成,每个节点配备 2 个 CPU 和 8 GiB 内存。
这足以持续摄入每秒 100 万行的数据流,对传入数据进行排序,并更新预聚合数据,同时,通过持续后台合并,将所有表中活跃数据分区的总数始终保持在 60 左右。
这种效率在实际应用中同样重要:它使我们能够经济高效地运行像 StockHouse 这样的演示,其所用的市场数据与本次基准测试中使用的相同,且这些数据能够实时流入并随之变得可供查询 (query-ready)。
③ 排序的原始数据和物化视图
ClickHouse 使用 MergeTree 表将原始数据以 排序形式 直接写入磁盘。该表用于处理原始数据的钻取 (drill-down) 工作负载。
与此同时,当新行到达时,一个增量物化视图 (materialized view) 会在 AggregatingMergeTree 表中维护预聚合 (pre-aggregated) 数据。该表用于处理仪表盘 (dashboard) 工作负载。
代码:原始 MergeTree 表、AggregatingMergeTree 表 和 增量物化视图。
在整个基准测试期间,原始 MergeTree 表始终保持排序,以实现快速钻取;AggregatingMergeTree 表存储用于仪表盘查询的预聚合数据,与基础表 (base table) 保持同步,没有数据滞后 (freshness gap)。这两个表始终保持最新并 可供查询。
④ 读取服务
读取查询运行在具有 1 个节点和 16 个 CPU 的 独立 ClickHouse Cloud 服务上。
我们为 Snowflake 配置了相同数量的读取计算资源,以确保不同系统之间的读取侧容量保持一致。
注意:根据普遍 共识,AWS 上的 Snowflake Gen2 Small 仓库 (warehouse) 使用 16 个 AWS Graviton3 核心 (cores)。ClickHouse Cloud 在 AWS 部署中同样采用 AWS Graviton3 核心,因此本次比较使两个读取路径都在相同 CPU 代的 16 个核心上保持对齐。
⑤ 持续查询工作负载
为模拟持续的读取工作负载,我们在整个基准测试期间定期运行两种类型的查询。
每隔 10 分钟,我们对预聚合表执行 4 个仪表盘查询。
每小时,我们对原始表执行 2 个即席下钻查询。这些下钻查询使用与原始表排序顺序匹配的过滤器。
我们在 Snowflake 上运行相同的查询调度,并采用等效的物理布局:原始数据按相同的键进行聚簇,聚合数据也以相同方式进行预聚合。
Snowflake 设置 1:标准表和 materialized views (物化视图)
首个 Snowflake 设置沿用了目前大多数 Snowflake 客户所使用的方案:标准表、标准 materialized views 和 Gen2 warehouses。
① 客户端设置
客户端 设置(即基准测试驱动程序)与 ClickHouse 设置相同。
它直接以二进制形式读取 Parquet row groups,将其组合成大约 100 万行的批次,并将这些批次发送到 Snowflake。这一次,客户端使用COPY INTO命令将 Parquet 数据加载到原始表中。
如前所述,客户端不执行任何解码、解压缩、编码或压缩操作。因此,其执行的客户端侧工作量与 ClickHouse 完全相同。
② 摄取仓库
对于数据摄取,我们再次选择了能够维持每秒 100 万行固定摄取速率的最小 Snowflake warehouse。
但这一次,根据 Snowflake 的建议,我们采用了 Gen2 硬件:具体而言,是一个配备 8 核 CPU 的 Gen2 X-Small warehouse。
目标仍不是追求最大加载吞吐量。
目标是寻求一种最低成本的设置,使其能够在固定摄取速率下稳定运行,以模拟新数据持续抵达的实时工作负载。
③ Serverless clustering (无服务器聚簇)
原始数据被写入一个标准的 Snowflake table 中。该表用于处理每小时的原始数据下钻工作负载。
数据排序工作由 Snowflake 的 无服务器集群服务 在后台处理,与原始基准测试保持一致。这样做的目的是确保原始表能够针对向下钻取查询保持物理优化。
Code: raw Snowflake table.
④ 物化视图刷新
为了在端到端基准测试中包含预聚合,我们使用了基于原始表的 Snowflake 物化视图 (materialized view)。仪表板工作负载会查询这个视图。
物化视图是 Snowflake 的企业版专属功能。刷新工作由 Snowflake 的 无服务器物化视图刷新服务 在后台处理。
Code: Snowflake materialized view.
⑤ 读取仓库
与 ClickHouse 的设置类似,我们使用独立的仓库分别处理数据摄取 (ingest) 和数据读取 (reads),从而将写入路径和查询路径彼此隔离。
对于读取操作,我们使用一个配备 16 个 CPU 的 Gen2 Small 仓库。
这与 ClickHouse 中用于读取的 CPU 数量相匹配。
⑥ 持续查询工作负载
我们运行与 ClickHouse 中相同的持续查询计划。
每隔 10 分钟,我们都会针对 预聚合数据执行 4 个查询,以模拟仪表板刷新操作。
每小时,我们都会针对原始表执行 2 个原始数据向下钻取查询。
Snowflake 设置 2:交互式表
第二种 Snowflake 设置对原始数据和预聚合数据都使用了 交互式表 (Interactive Tables)。
交互式表目前 仅在选定区域可用。为了进行测试,我们必须在一个受支持的区域创建 Snowflake 账户。因此,我们提供了两种 Snowflake 配置方案:一种是广泛可用的、采用标准表和物化视图的设置,另一种是在可用区域中采用更新的交互式表的设置。
① 客户端设置
该客户端与 ClickHouse 设置和第一个 Snowflake 设置中的客户端相同。
它直接以二进制形式读取 Parquet 行组,将它们组合成大约 100 万行的批次,并使用COPY INTO将数据加载到 Snowflake。客户端不执行任何解码、解压缩、编码或压缩操作。
② 摄取仓库
与之前相同,数据摄取使用能够维持每秒 100 万行固定摄取速率的最小 Snowflake 仓库。
我们使用一个配备 8 个 CPU 的 Gen2 X-Small 仓库。
③ 原始数据刷新
传入数据首先进入一个标准的 Snowflake 表。原始的交互表(Interactive Table)随后由用户管理的仓库从该源表进行维护,刷新按需触发以满足设定的目标延迟。这与标准的交互表模式相对应。
我们为原始交互表设置了 10 分钟的目标延迟,该表用于处理每小时的下钻工作负载。
(通过 Snowflake 管理的摄取路径,可以直接将数据摄取到交互表中。我们单独讨论这种情况,因为它不涵盖此处测量的预聚合路径。)
代码和文档:标准 Snowflake 表、原始交互表、目标延迟刷新行为以及仅插入限制。
④ 预聚合数据刷新
预聚合数据也存储在交互表(Interactive Table)中。
在此,刷新仓库会定期传输自上次刷新以来的新行,对其进行聚合,并将结果合并到预聚合的交互表(Interactive Table)中。
我们使用 1 分钟的目标延迟(这是可用的最小目标延迟)。 由于此表承载着仪表板工作负载,我们配置了 Snowflake 允许的最新的预聚合路径。
这样我们就能将其与 ClickHouse 增量物化视图(它们在数据摄取路径上更新)进行比较,并衡量在 Snowflake 中尽可能接近该新鲜度模型所需的成本。Snowflake 还提供交互式物化视图 (Interactive Materialized Views);我们将 单独测试 该路径。
由于 Small、Medium 和 Large 仓库都无法可靠地将预聚合刷新保持在 1 分钟的目标延迟内,我们转而使用 Gen2 X-Large 仓库来执行刷新操作。
代码和文档:预聚合交互式表、聚合查询、目标延迟行为、交互式物化视图 和 刷新大小比较。
⑤ 交互式读取仓库
对于读取操作,我们使用一个配备 16 个 CPU 的 Small Interactive Warehouse。
这与 ClickHouse 和首次 Snowflake 设置中用于读取的 CPU 数量保持一致。
与标准仓库不同,Interactive Warehouse 还配备了一个 大型缓存。对于 Small Interactive Warehouse,该缓存大约为 600 GB,使交互式表的工作集能够驻留在内存中。
值得注意的是,Interactive Warehouses 具有 1 小时的最短计费时长,并且自动暂停的最小设置为 24 小时。在此基准测试中,此计费模型与工作负载相匹配:我们正在衡量一个持续运行的实时分析服务,其中包含持续的数据摄取、刷新和查询。
⑥ 持续查询工作负载
我们沿用与之前相同的持续查询计划。
每隔10分钟,我们会对预聚合数据运行4次查询,以模拟仪表盘刷新。
每小时,我们对原始 Interactive 表运行2次原始数据钻取查询。
结果:ClickHouse 对比 Snowflake 标准表
首先,我们将 ClickHouse 与大多数客户目前可用的 Snowflake 配置进行比较:标准表 (standard tables)、标准物化视图 (materialized views)、无服务器集群 (serverless clustering)、无服务器 MV 刷新 (serverless MV refresh) 和 Gen2 仓库 (Gen2 warehouses)。
性能:持续数据摄入下的延迟与数据新鲜度
在这些测量中,两个系统都使用相同的读取端计算资源:16个AWS Graviton3核心。
查询计划也保持一致。
仪表盘查询:预聚合仅在保持最新时才发挥作用
这张图表展示了我们每隔10分钟对预聚合数据执行的4次仪表盘查询。X轴表示摄入到原始表中的行数,从运行开始到大约28小时后达到1000亿行。Y轴表示查询延迟。
所有各次查询的运行详情都可在 CostBench 存储库中获取:ClickHouse,Snowflake。
随着原始表的增长,ClickHouse 的性能表现几乎完全平稳,仪表盘查询延迟保持在个位数毫秒范围内。这是因为 ClickHouse 在数据摄入过程中同步更新预聚合表,从而持续保持最新并处于查询就绪状态。
Snowflake 的标准物化视图 (materialized-view) 配置表现截然不同。其查询延迟明显更高且波动剧烈:较简单的仪表盘查询延迟维持在数秒左右,而负载较高的仪表盘查询则跃升至高个位数甚至数十秒的范围。
症结在于数据的新鲜度。即便 Snowflake 物化视图 (materialized view) 本身存在滞后,它仍能返回最新摄入数据的结果。在这种情况下,Snowflake 必须在查询时将物化视图与原始表中缺失的行进行合并。对于仪表盘工作负载而言,这意味着刷新速度不仅会变慢,还会变得不可预测。
新鲜度滞后:慢速仪表盘背后的隐性成本
下图直接展示了底层的新鲜度滞后。
我们通过每分钟使用SHOW MATERIALIZED VIEWS命令轮询 (polling) Snowflake 的物化视图元数据来测量此滞后。详细的新鲜度样本可在此处获取,请参阅behind_by列。
ClickHouse 能够保持数据最新,是因为其物化视图在数据摄入路径上是同步更新的。
Snowflake 的物化视图通过一个无服务器 (serverless) 后台服务进行刷新,该服务没有新鲜度服务等级协议 (SLA),用户也无法控制其运行时间或所消耗的计算资源。在本次测试中,Snowflake 物化视图持续处于滞后状态,其滞后时间反复达到约 60 到 72 分钟。
钻取查询:聚类有所帮助,但无法维持稳定延迟
下图展示了我们每小时针对原始数据运行的两个钻取查询。其中,x 轴表示从测试开始到约 28 小时后,原始表中摄入的行数,最高达 1000 亿行;y 轴则表示查询延迟。
所有每次查询的运行详情均可在 CostBench 仓库中获取:ClickHouse,Snowflake。
这些查询使用了与原始表的排序/聚簇键相匹配的过滤器。换句话说,两个系统都获得了相同的物理布局优势:ClickHouse 依照该键进行排序,而 Snowflake 则依据相同的键进行聚簇。
即便如此,其模式与我们首次读性能基准测试中的结果一致:随着数据集的增长,不同系统的表现开始出现差异。ClickHouse 的性能基本保持平稳,数据规模对其影响不大。而 Snowflake 则变得越来越慢,在测试结束时响应时间达到了数秒。
成本:数据摄入、维护与读取
在成本方面,我们采用了 AWS us-east 区域的企业版定价。该定价模式使 Snowflake 能够使用需要企业版才能提供的物化视图(Materialized Views);而 ClickHouse 的物化视图即使在开源版本中也可用。
实时数据路径成本:确保数据可查询
下图展示了测试运行前 28 小时内,实时数据路径的总成本:该过程以每秒 100 万行(总计 1000 亿条)的持续速率摄入新数据,同时保持原始数据已排序/聚簇,并维护预聚合数据。
对于 ClickHouse,数据摄入服务使用了 2 个节点,每个节点配备 2 颗 CPU 和 8 GiB 内存。根据ClickHouse Cloud 定价,这相当于 2 个计算单元 (compute units)。在 28 小时的运行期间,其成本为:2 个计算单元 × 28 小时 × $0.3903/小时 =$21.86。
对于 Snowflake,数据摄入仓库采用了 Gen2 X-Small warehouse。以每小时 1.35 个积分 (credits) 和每积分 3 美元的价格计算,数据摄入仓库的成本为:1.35 个积分/小时 × 28 小时 × $3/积分 =$113.40。
Snowflake 剩余的写入相关成本来自于无服务器服务 (serverless services)。我们从 Snowflake 系统表中提取消耗的积分,并以相同的每积分 3 美元价格进行计算:无服务器聚簇 (serverless clustering) 成本为 54.12 积分 × $3 =$162.37;无服务器物化视图刷新 (serverless materialized-view refresh) 成本为 3.60 积分 × $3 =$10.8。
综上所述,Snowflake 的实时数据路径总成本为$286.58。
在不计入查询成本的情况下,Snowflake 的标准设置在保持新鲜数据可供查询方面的成本已高出约13 倍。
查询成本:执行相同的调度任务
最后,我们衡量读取侧的表现:在 28 小时运行期间,每个系统需要多少运行时长和查询成本来处理相同的连续查询调度。
对于查询成本,我们采用与最初的 读取侧基准测试 方法论中相同的 简化:即 累积查询运行时长 × 读取侧计算价格,如同查询计算以完美的每秒粒度计费一样。
实际上,Snowflake 和 ClickHouse Cloud 都会持续 计费,直到达到可配置的空闲超时时间。但这种标准化方法直接比较了查询引擎的效率:
在给定量的付费计算时间内,系统能够完成多少查询工作?
下方图表展示了结果。
每个查询的运行详情均可在 CostBench 代码仓库中查阅:ClickHouse 的 仪表板查询 和 钻取查询,以及 Snowflake 的 仪表板查询 和 钻取查询。
为了计算查询成本,我们使用连续读取工作负载的累计运行时长,再乘以读取侧计算的价格。
ClickHouse 使用一个配备 16 个 CPU 和 64 GiB RAM 的读服务,相当于 8 个计算单元 (compute units):8 个计算单元 × $0.3903/小时 × 70.4 秒 =$0.061
Snowflake 使用一个配备 16 个 CPU 的 Gen2 Small 读仓库 (read warehouse)。按照每小时 2.7 credits (积分) 且每 credit 3 美元计算,即每小时 $8.10:2.7 credits/小时 × $3/credit × 5,017 秒 =$11.288
这使得 ClickHouse 在处理此工作负载的查询计算时,成本降低了约 185 倍,这还不包括新鲜数据路径的成本。
成本-性能:全路径得分
如何在每美元投入中,获得最优的全路径实时性能?
为了直接比较全路径实时成本效益,我们将成本和性能整合成一个单一的衡量指标,该指标值越低表示表现越好。
该指标的计算公式为:
(新鲜数据路径成本 + 查询成本)× 总查询运行时间
这个指标体现了基本的成本-性能权衡:系统若能保持路径低廉并快速响应查询,则得分更优。昂贵的系统得分较差,运行缓慢的系统得分亦差。当一个系统既昂贵又迟缓时,这两个负面影响还会叠加放大。
Snowflake 的标准配置得分高出 969 倍。
这正是叠加效应:Snowflake 需要支付更多成本来维持数据路径运行,并且仍需要更长的运行时间来处理相同的持续查询调度。
更何况,这还未计入预算差异。若按照 Snowflake 的支出水平,ClickHouse 甚至可以扩展至更大规模的服务,进一步降低延迟,而总成本依然低于 Snowflake。
结果:ClickHouse 与 Snowflake 交互式表对比
在上一节中,我们针对 Snowflake 广泛可用的标准表路径对 ClickHouse 进行了基准测试。接下来,我们将针对 Snowflake 的 Interactive Tables 设置 重复运行相同的 CostBench 工作负载。
工作负载、客户端行为、数据摄取速率、查询调度以及读取端 CPU 核心数均保持不变。唯一变化的是 Snowflake 的服务路径:原始数据和预聚合数据现在存储在 Interactive Tables 中,由用户管理的仓库进行刷新,并通过一个带有大容量缓存的 Interactive Warehouse 提供服务。
值得注意的是:
在这些测量中,两个系统都使用了相同的读取侧计算资源:16 个 AWS Graviton3 核心。
性能:Interactive Tables 提升了读取性能,但未能消除差距
这些图表沿用了上述相同的格式:x 轴表示摄入的原始行数,在大约 28 小时后累计达到 1000 亿行;y 轴则表示查询延迟。
仪表盘查询:Interactive Tables 速度更快,但平稳性仍有不足
对于仪表盘查询,Interactive Tables 结合交互式仓库 (interactive warehouse)显著改善了 Snowflake 的延迟,优于标准的物化视图 (materialized-view)配置。然而,尽管使用了相同的读取端 CPU 资源,ClickHouse 的延迟仍然更低且波动更小。
所有查询的运行详情均可在 CostBench 仓库中查阅:ClickHouse,Snowflake。
交互式预聚合结果存在一个刷新周期的滞后即使 Snowflake 仪表盘查询能够快速返回,它们也是从一个预聚合的 Interactive Table 中读取数据,该表存在 1 分钟的目标延迟。ClickHouse 保持更快的速度和实时的数据,因为其预聚合发生在数据摄取路径上。
数据新鲜度:调度刷新必须跟上
下一张图表展示了在 Interactive Tables 方案中,保持预聚合数据新鲜度所需的措施。
我们通过每分钟对 Snowflake 的 INFORMATION_SCHEMA.INTERACTIVE_TABLE_REFRESH_HISTORY 表进行轮询 (polling)来测量此延迟,相关结果请参见此处。
ClickHouse 在整个运行过程中保持数据实时,因为当新行插入时,其物化视图 (materialized views)会同步更新。
原始 Interactive Table 的表现符合预期:在 10 分钟的刷新目标下,它在所有测试的仓库规模中都保持在该目标范围内。这足以满足每小时钻取工作负载对原始表的数据新鲜度要求。
更具挑战性的部分是预聚合的 Interactive Table。如前所述,我们使用了 Snowflake 允许的最小刷新间隔(即 1 分钟),因为该表服务于股票报价仪表盘的工作负载,并且是 Snowflake 能达到的最接近 ClickHouse物化视图 (materialized views)的效果。
Gen2 Small 刷新仓库在大约 3 小时后开始出现延迟,Gen2 Medium 在大约 8 小时后,而 Gen2 Large 则在大约 15 小时后。图中的红色交叉标记了每种配置无法将预聚合的交互式表 (Interactive Table) 更新保持在配置的 1 分钟目标内的时间点。
这并非因为 Snowflake 在每次刷新时都重新聚合整个原始表。正如我们通过系统表查询所确认的,对预聚合的交互式表的刷新是增量的。即便如此,刷新仓库仍需处理新行、对其进行聚合,并将结果合并到目标表,所有这些都必须在下一次刷新开始前完成。
因此,最终设置采用了 Gen2 X-Large 刷新仓库。它在最初的 24 小时内,成功使两个交互式表的更新都保持在配置的目标范围内。
预聚合的延迟仍在缓慢增加。虽然在第一天没有超出 1 分钟的目标,但曲线并未趋于平稳。对于更长时间的运行,Snowflake 将需要更多的刷新计算资源,或者一个更宽松的新鲜度目标。
钻取查询:交互式仓库缓存有所帮助,但扩展性挑战依然存在
对于钻取查询,相较于标准表设置,交互式表显著提升了 Snowflake 的性能。
每次查询的运行详情均可在 CostBench 仓库中获取:ClickHouse,Snowflake。
然而,随着数据量的增长,这种性能提升未能保持平稳。
尽管在最初的 1000 亿行数据范围内,工作集仍能完全载入交互式仓库缓存中,但 Snowflake 的延迟随着数据量的增加而上升。ClickHouse 则保持平稳得多,即使没有交互式仓库缓存。对于其中一个钻取查询,当数据量达到约 500 亿行时,Snowflake 的速度已低于 ClickHouse;而到测试结束时,两个钻取查询的延迟都已达到或超过 ClickHouse 的水平。
核心观点: 即使在一个轻量级数据集上,仅经过约一天的持续数据摄取(速率为每秒 100 万行,规模适中),Snowflake 交互式表 (Interactive Tables) 在下钻查询工作负载方面的延迟已达到或超过 ClickHouse。
扩展性说明
关键在于,即使工作集尚能完全放入交互式仓库 (Interactive Warehouse) 缓存中,查询延迟便已开始增加。
这引出了下一个关于扩展性的问题:当工作集大到即使是最大可用交互式仓库缓存也无法容纳时,又会发生什么?
Snowflake 的交互式仓库模型 (Interactive Warehouse model) 也存在一个固定的 5 秒查询超时限制。一旦查询时间超过此阈值,Snowflake 便建议使用备用仓库 (fallback warehouse)。这引入了额外的成本考量:备用仓库必须在需要时随时可用,而且用户所感知的运行时,将包含失败的首次尝试以及在备用计算资源 (fallback compute) 上的重试时间。
成本:摄取与刷新
相较于标准的 Snowflake 配置,交互式表降低了查询路径的成本,但代价是刷新操作的成本随之增加。
实时数据路径成本:刷新成为主要开销
对于 ClickHouse 而言,实时数据路径保持不变:相同的摄取服务负责数据摄取、排序、合并以及物化视图 (materialized-view) 更新。如前所述,其成本为:2 个计算单元 × 28 小时 × $0.3903/小时 =$21.86。
对于 Snowflake 而言,摄取仓库 (ingest warehouse) 同样保持不变。Gen2 X-Small 型摄取仓库的成本为:1.35 credit/小时 × 28 小时 × $3/credit =$113.40。
主要差异体现在刷新环节。为了将预聚合 Interactive Table 的数据新鲜度保持在 Snowflake 设定的最小 1 分钟刷新目标,刷新仓库 (refresh warehouse) 必须几乎持续运行。最终的配置方案采用了 Gen2 X-Large 型刷新仓库。按照 21.6 credit/小时和 $3/credit 的费率计算,其成本为:21.6 credit/小时 × 28 小时 × $3/credit =$1,814.40。
综上所述,Snowflake 交互式表 (Interactive Tables) 的实时数据路径成本为 $1,927.80。
在不计查询成本的情况下,为维持实时数据路径的查询就绪状态,其成本大约是 ClickHouse 的 88 倍。
查询成本:交互式表读取成本逐渐接近
对于查询成本,我们沿用了标准设置部分中描述的每秒运行时标准化方法。
下图展示了 Interactive Tables 读取工作负载的总累计运行时间与查询成本。
所有查询运行的详细信息均可在 CostBench 仓库中获取:ClickHouse 的仪表盘查询和钻取查询,以及 Snowflake 的仪表盘查询和钻取查询。
ClickHouse 仍使用与之前相同的读取服务配置:16 颗 CPU 和 64 GiB 内存,即 8 个计算单元。8 个计算单元 × $0.3903/小时 × 70.4 秒 =$0.061
Snowflake 采用一个小型 Interactive Warehouse (交互式仓库)。按每小时 1.2 credit、每 credit $3 计算,即每小时 $3.60。1.2 credit/小时 × $3/credit × 144 秒 =$0.144
在查询计算方面,即便使用相同的读取端 CPU 数量,ClickHouse 仍然快约2 倍,成本便宜约2.4 倍。
成本与性能:全路径得分
现在我们可以直接比较整个路径:即保持数据实时更新并可供查询的成本,以及系统为持续工作负载提供服务所需的运行时间。
与标准设置相比,Interactive Tables 显著提升了 Snowflake 的性能得分。
然而,整体路径的运行成本仍然高昂得多。Snowflake 的 Interactive Tables 设置的表现差了 180 倍。
这一差距意义重大:
ClickHouse 用户即使投入更多计算资源,也能在延迟方面大幅超越 Interactive Tables,并且其总成本仍将低于 Snowflake。
为何数据新鲜度机制至关重要
上述结果还揭示了在新数据持续写入时,各个系统如何保持派生数据实时更新的更根本差异。
①新数据持续写入。这是整个基准测试的起点:基础表数据不断变化,因此预聚合必须跟上实时数据流,而不是静态数据集。
②Snowflake 实体化视图 (Materialized View) 异步刷新。这正是标准 Snowflake 配置所展现的情况:当数据持续写入时,实体化视图反复比基础表滞后 60 到 72 分钟。尽管 Snowflake 仍能通过在查询时将实体化视图与原始表中缺失的数据行相结合来返回最新的查询结果,但这正是导致仪表盘延迟变得缓慢且不可预测的原因。
③Snowflake Interactive Tables 使用计划刷新 (scheduled refresh)。Interactive Tables 提升了新鲜度控制能力,但它们仍通过计划刷新机制运作。对于预聚合,最小目标延迟为1 分钟。这意味着刷新仓库成为连续写入路径的一部分:它必须在数据写入期间以该频率运行,并且需要根据负载配置资源,确保每次刷新都能在下一次刷新开始前完成。如果无法做到,延迟便会累积。随着表的增长,维持 1 分钟的刷新目标将成为一个可扩展性和成本方面的挑战。
④ClickHouse 增量实体化视图 (incremental materialized views) 在数据写入时更新。ClickHouse 采取了不同的策略:当新数据插入时,实体化视图会同步更新。因此,预聚合表始终与基础表保持一致,无需等待独立的刷新周期。
⑤这将改变实时应用场景的可能性。对于仪表盘应用,1 分钟的刷新目标或许可以接受。然而,对于亚分钟级 (sub-minute) 的决策工作负载,特别是在金融服务和欺诈检测等领域,其有效新鲜度窗口是以数百毫秒来衡量的,此时计划刷新机制就已经太迟了。在这些场景中,数据的新鲜度直接决定了系统是否能够支持此类工作负载。
存储占用:非基准测试的决定性因素
为求完整,我们还测量了每个系统的存储占用。
存储在运营中固然重要,但它并非本次基准测试的决定性因素。ClickHouse Cloud 和 Snowflake 都将持久化数据存储在低成本的对象存储 (object storage) 上。在此工作负载中,每月存储费用与持续数据摄入、维护查询就绪的数据布局、刷新派生数据以及响应查询的成本相比,显得微不足道。
下图展示了在持续摄入数据最初的31.4 小时后,测得的存储占用空间。截至那时,每个系统已以每秒100 万行的速度,摄入了大约1130 亿行股票报价数据,即每秒约75 MB。
测量查询:ClickHouse,Snowflake。
该图表采用了测试区域当前的官方存储价格:ClickHouse Cloud 的价格为每 TB/月$25.30,而 Snowflake 在 AWS US East 区域的价格为每 TB/月$23.00。
ClickHouse 原始数据:
362 GiB × 2^30 / 10^12 × $25.30 = $9.83/月
Snowflake 标准原始数据:
701 GiB × 2^30 / 10^12 × $23.00 = $17.31/月
Snowflake 交互式原始数据:
2.9 TiB × 2^40 / 10^12 × $23.00 = $74.12/月
预聚合表 (pre-aggregated tables) 也采用了相同的计算方法。
这也揭示了 Snowflake Interactive Tables 带来的一个值得注意的存储方面的影响。
原始 Interactive Table 的大小约为 Snowflake 标准原始表的4.2 倍,约为 ClickHouse 原始表的8.2 倍。
这与 Snowflake 的文档内容一致:
交互式表可能比同等的标准表更大,这归因于数据编码的差异以及额外的索引。
如果以相同的摄取速率持续整月(730 小时),月底的存储容量将大致按如下方式变化:
Data path | After 31.4h | Cost at that size | Projected after 730h | Cost at projected size |
|---|---|---|---|---|
ClickHouse 原始数据 | 362 GiB | $9.83/月 | ~8.2 TiB | ~$229/月 |
Snowflake 标准原始数据 | 701 GiB | $17.31/月 | ~15.9 TiB | ~$402/月 |
Snowflake 交互式原始数据 | 2.9 TiB | $74.12/月 | ~67.4 TiB | ~$1,724/月 |
需要注意的是,我们并不确定交互式表的存储大小是否线性增长,这仅是我们的假设。
尽管如此,与 CostBench 中测量的计算和刷新成本相比,绝对存储成本依然很低。整个链路的成本性能差距主要由运行系统决定,包括摄取计算、集群或刷新工作,以及在新数据不断到达时的查询执行。
展望:更多路径和更重工作负载
CostBench 是一个用于在不同系统设计下,测试完整实时分析链路的框架。
托管摄取路径
我们计划测试的下一个变体是 Snowflake 的托管摄取路径。在该路径下,Snowpipe Streaming 可以直接写入原始数据交互式表,但无法直接维护预聚合数据。
对应的 ClickHouse 路径是 ClickPipes。
这样,我们就可以在无需借助本次基准测试中用于直接写入数据的轻量级客户端的情况下,对双方的托管摄取能力进行比较。
更高查询并发
我们还将利用相同的框架,加大读取端的压力,独立扩展查询工作负载,并在新数据不断抵达的同时,测试更高的并发性。
更繁重的实时数据集
如开篇所述,本次测试特意从较为简单的场景入手:采用小规模、窄表数据集,搭配简单的排序键,以及一种对 Snowflake 有利的数据写入模式。
接下来,我们将在另一个极端场景重复测试:使用一个更宽、更繁重的数据集,这种数据形态在 ClickHouse 实时分析工作负载中极为常见。
这将展示两种极端情况:既有最有利于 Snowflake 发挥性能的理想场景,也有 ClickHouse 擅长应对的复杂场景。
当然,我们也欢迎 Snowflake 提出其他需要测试的配置方案。该框架具有灵活性,关键在于比较需涵盖完整路径。
结论:完整路径将改变结果
Snowflake 的回应帮助我们厘清了问题。许多建议都是有效的优化措施,例如简化集群、将读取操作迁移至交互式表 (Interactive Tables),或调优刷新路径。
然而,实时系统是端到端的完整路径系统。优化其中一个阶段,可能会将成本转嫁到其他环节:例如,更快的读取可能需要更多的刷新计算资源;更及时更新的预聚合可能需要一个持续运行的刷新数仓;而更好的物理数据组织则可能增加维护工作量。
因此,我们对整个端到端过程进行了衡量。
部分测试结果有所改善。交互式表 (Interactive Tables) 使得 Snowflake 的读取速度远超标准实体化视图 (materialized-view) 配置。但当我们衡量了完整路径——包括数据摄取、物理组织、预聚合新鲜度、刷新成本以及持续查询服务——这些权衡取舍变得更为清晰。
在最初的查询就绪数据基准测试中,ClickHouse 的写入侧成本效益比 Snowflake 高出28 倍。在此次扩展基准测试中,ClickHouse 的成本效益比 Snowflake 的标准实体化视图配置高出969 倍,比 Snowflake 的交互式表配置高出180 倍。
核心要点在于:实时分析并非仅仅追求查询速度,它更关乎于确保新数据随时可供查询、保持衍生数据同步更新,并持续提供低延迟查询服务,同时避免刷新操作成为主要的成本负担。
对于亚分钟级决策工作负载 (sub-minute decisioning workloads) 而言,数据新鲜度模型的重要性愈发凸显。在所有测试路径中,唯有 ClickHouse 的增量实体化视图 (incremental materialized views) 能够使预聚合数据与基表 (base table) 持续保持同步,且几乎零延迟。
ClickHouse 专为实现全路径、高成本效益的实时分析而设计。MergeTree 表 (MergeTree tables) 能够确保原始数据有序且随时可供查询。AggregatingMergeTree 表 (AggregatingMergeTree tables) 则能使预聚合数据持续保持新鲜,实现无缝刷新。此外,其查询引擎在数据量不断增长的同时,依然能保持低延迟。
我们最新的 迁移案例 展示了生产环境中同样的端到端效率。Appcues 将面向客户的实时分析从 Snowflake 迁移到 ClickHouse Cloud,处理了高达1.31 PB 的数据和 4100 亿个事件。迁移后,P95 查询延迟从 20 多秒降至 2 秒以内,摄取延迟从 10 多分钟缩短至约 5 秒,即使新增了工作负载,分析成本也随之降低。
这正是 CostBench 旨在评估的优化路径。我们将继续测试更多的系统、更丰富的摄取路径、更庞大的数据集以及更高的并发性。敬请期待。
关于我们:
ClickHouse 是面向 AI 时代打造的高性能实时分析数据库,能够以极致性能处理海量数据分析任务。凭借高并发、低延迟和云原生架构,ClickHouse 广泛应用于可观测性、数据仓库、实时分析及 AI 数据基础设施等场景。我们致力于帮助企业在公有云平台上构建安全、弹性且高性价比的实时分析与 AI 数据平台,加速释放数据价值,推动智能化创新与数字化转型。目前,Trip.com、DiDi、Meta、Sony、Netflix、Deutsche Bank、Sierra、Cloudflare 等全球领先企业均在使用 ClickHouse 支撑其关键业务和数据分析平台。