ClickHouse Cloud 与 Snowflake 实时性价比对比:CostBench 测试中的 412 倍差距来

本文字数:18189;估计阅读时间:46分钟

作者:Tom Schreiber and Lionel Palacin

编者按: 本文译自 ClickHouse 原博客(链接点文末-查看原文)。 原文围绕「新鲜数据通路的架构差异如何决定实时分析的每美元性能」展开。把预聚合放进存储引擎,省下的不只是刷新周期,还有查询时的补救成本。对比的价值在于把性能差距拆解成可归因的工程选择。

TL;DR

实时分析系统要想让查询答案既新又快,就得有一条高效的新鲜数据通路。CostBench 对比了 ClickHouse Cloud 和 Snowflake:两者都摄入 1132 亿条股票行情报价,并持续处理同一套查询负载。

• ClickHouse Cloud 把摄入、排序和预聚合都整合在存储引擎里。 原始数据与汇总数据始终同步,不需要单独的刷新周期,查询也就不会接手尚未完成的准备工作。

• Snowflake 的摄入与预聚合由不同服务分别推进。 一旦准备工作落后,要拿到最新的答案就得在查询时补做额外工作。它的变通方案会在新鲜度、延迟、基础设施和成本之间带来取舍。

• ClickHouse Cloud 每美元带来的端到端实时性能,比测试中的 Snowflake 方案高 412 倍 ,靠的是成本更低的新鲜数据通路加上更快的查询。

412 倍的差距从何而来

第 1 部分说明,新鲜数据通路会从两方面影响每美元性能:它直接承担让新数据可被查询的成本,同时决定查询引擎还剩多少工作要做。

第 2 部分考察这两种影响在 ClickHouse Cloud 和 Snowflake 上的具体表现。我们以每秒 100 万行的速度,把同一批 1132 亿条股票行情报价分别摄入两套系统,用的是各自推荐的实时组件。整个摄入过程中,两边都在运行相同的聚合查询和下钻查询。

数据摄入、持续的数据准备和查询服务是同时进行的。下方的交互式图表展示了准备工作如何影响留给查询的工作量。可以观看循环动画,或拖动滑块:随着排序和预聚合逐步追平,查询引擎需要扫描和聚合的工作量随之减少;一旦准备工作落后,这部分工作量就会增长,查询延迟和成本也会上升。

完整的运行闭环就是对比边界。两个系统接收的是同一份数据流、同一套 schema、同样的查询负载和调度安排。

我们在各系统间为原始数据和每日预聚合配置了对应的排序键或聚簇键。这些布局支持负载中的股票代码过滤条件。预聚合按股票代码和日期对行情报价分组,维护聚合查询所需的计数、求和以及价格最小值和最大值。因此,随着新行不断到达,每个系统都必须针对同一查询负载保持同样的预聚合数据同步更新。

查询服务的计算资源匹配在约 16 个 CPU,同时每个系统保留其推荐架构和完整的按量计费新数据路径。

基准测试方法与配置细节:

共享测试框架

相同的源文件、schema、行解码逻辑、负载生成代码、客户端主机(AWS EC2 m6i.8xlarge)、速率控制器、调度器、计时和结果记录逻辑驱动两个系统;只有目标端专用的投递适配器不同。完整的共享方法见此。

实时,而非批量加载

CostBench 模拟的是实时分析系统,其中新数据在源头持续生成,且必须在到达时就变得可供查询。因此,该测试框架模拟的是有节奏的持续写入,而不是批量加载或对已有数据的回填。

数据集与布局

两个系统接收相同的完整 1132 亿行 NBBO 股票市场数据集:窄表,12 列。

两个系统使用以下排序键或聚簇键:

• 事件级数据: (sym, t) ------ 股票代码和事件时间戳。

• 每日预聚合: (sym, day) ------ 股票代码和日期。

负载与查询调度

测试框架将源数据作为一条连续流回放,目标速率为每秒 100 万行。从写入开始到最后一行为止,同样的四个交互式聚合查询每 10 分钟运行一次,同样的两个选择性下钻查询每小时运行一次。

资源规模确定策略

我们在各平台允许的范围内,尽可能对齐查询服务计算资源。ClickHouse Cloud 使用一个读节点,配置 16 个 CPU 和 64 GiB 内存;Snowflake 使用一个 Small Interactive Warehouse 和一个 Gen2 Small 备用仓库,由于 Snowflake 不公布 CPU 数量,两者估计都约为 16 个 CPU。这一估算参考了 SELECT.dev 和一份独立的 Gen2 检查。对于摄取,ClickHouse 使用校准期间能够维持目标速率的最小高可用配置------两个节点,各 2 个 CPU------而 Snowpipe Streaming 和 Interactive MV 刷新则作为单独计量的无服务器服务运行。它们的全部计量工作量仍计入 Snowflake 的新数据路径成本。

四个 CPU 核心上的完整新数据路径

写入器利用率结果 展示了双节点摄取服务如何处理持续摄取和后台维护。后台合并每秒处理数百万行,而每个分区的最大活跃 part 数保持在 100 左右。CPU 使用量约为该服务 4 个可用核心中的 3.1 个核心,表明利用率持续稳定且仍有余量。跟踪到的内存使用量保持在服务容量之内。

我们为高可用保留了两个节点,因此报告的摄取成本包含 高可用部署的两个节点。

平台最佳实践配置

我们按照各厂商推荐的低延迟组件和文档中记录的最佳实践,为每个平台配置新数据路径,让传入数据保持可查询。这些路径之间的差异也是基准测试的一部分。

运行与报告范围

为简洁起见,下文大多数图表展示到 1000 亿行里程碑 的结果。基准测试本身一直持续到完整的 1132 亿行数据集 全部摄入两个系统,成本计算也覆盖这次完整摄取。

目标速率与实测速率

按每秒 100 万行的目标速率,摄取 1000 亿行大约需要 28 小时。客户端限速、并行摄取流和批大小调整,都试图实现端到端的精确速率,但无法保证做到;一次运行超过一天时,吞吐出现波动很正常。实测吞吐量平均约为 ClickHouse 每秒 86 万行 ,Snowflake 每秒 90 万行。因此,ClickHouse 在大约 32 小时后达到 1000 亿行,并在大约 37 小时后完成 1132 亿行的数据集;Snowflake 在大约 31 小时后达到 1000 亿行,并在大约 35 小时后完成该数据集。

在保持各系统外围工作负载不变的情况下,对比现在转向两种架构内部。

新数据路径架构

本轮 CostBench 采用推送式摄取:共享客户端通过各系统推荐的低延迟摄取路径,发送同一条限速流。Snowflake 走的是 Snowpipe Streaming;ClickHouse Cloud 走的是原生异步插入。

为什么比较 Snowpipe Streaming 与 ClickHouse 异步插入?

相同的摄取问题

在可观测性、面向客户的应用、IoT、欺诈检测和分析型智能体等领域,实时应用常常从大量客户端产生小批量、高频写入。摄取路径必须持续接收这些写入,并将它们合并成高效的存储写入。Snowpipe Streaming 和 ClickHouse 异步插入都为此提供服务器端缓冲。

SNOWFLAKE:托管式摄取服务

Snowpipe Streaming 让应用程序直接提交数据行,无需自行管理暂存文件。这里采用的高性能架构中,客户端针对 PIPE 对象打开通道。Snowflake 的摄取服务负责缓冲、模式校验、已配置的转换,以及可选的预聚簇,完成后才把数据行写入目标表。摄取计算由 Snowflake 负责管理和扩缩,费用按未压缩数据量单独计费。

CLICKHOUSE:引擎内完成摄取

应用程序发送普通的 INSERT 请求,并启用 async_insert。每个接收节点会缓冲兼容的请求,合并为更大的写入,并配有可随流量变化调整的自适应刷新超时。这一能力在开源 ClickHouse 和 ClickHouse Cloud 中都是原生的。

引擎在摄取期间还会做排序和转换。接收节点写入 data parts 时,会按每个目标 MergeTree 系列表的排序键对传入行排序。数据在真正存储之前,就可以在插入路径上被过滤、路由、丰富(字典查找、UDF)和重塑。这些操作都在接收插入的节点上执行。

在 ClickHouse Cloud 中,摄取可以运行在专用服务上,其计算资源独立扩缩,与对外提供查询的服务互不影响,同时共享同一份已存储数据。

重试与恢复

Snowpipe Streaming 的 offset token 记录每个通道已提交的源端进度。重启之后,应用程序必须取回最后提交的 token,把它映射回源端,再从下一条记录继续。Snowflake 的 Kafka 连接器会为 Kafka 分区完成这一映射。而对自建应用来说,恢复逻辑得由应用自己实现;offset token 本身并不能让重发已提交的数据行变得安全。

ClickHouse 通过插入去重实现幂等重试。携带相同数据的重试插入会被服务端识别并丢弃(同步插入和异步插入都会去重,依赖它们的物化视图也不例外)。崩溃或确认丢失之后,无需维护 offset 记录:客户端把最近的批次重发一遍即可,已经落地的数据 ClickHouse 会自动忽略。

CLICKPIPES 的适用位置

ClickPipes 负责管理数据接入,来源可以是 Kafka、对象存储、Postgres 等外部系统。所以该拿什么来对比,取决于数据从哪里来:

• 应用直接推送行数据: Snowpipe Streaming 与 ClickHouse 原生的异步插入------也就是本文所测的对比。

• Kafka topic: Snowpipe Streaming 搭配 Snowflake 的 Kafka connector,以及 Kafka ClickPipes。

• 对象存储中的文件: 经典 Snowpipe 与 Object Storage ClickPipes。

后两种搭配比较的是完整集成方案,即从外部数据源消费数据。本次 benchmark 衡量的是应用直接写入表的路径。

我们从 ClickHouse Cloud 开始,沿着它的新鲜数据路径走一遍:从行数据进入,到事件级数据与预聚合数据可供查询。

接入数据流 - ClickHouse Cloud

本次 benchmark 使用了专用的 ClickHouse Cloud 接入服务,两个 2 CPU 节点实现高可用------这是校准过程中能稳定支撑目标吞吐的最小 HA 配置。客户端以共享方式,通过引擎内置的异步插入发送行数据。

还是这两个节点,同时负责排序、增量预聚合和后台合并,跑完整个 fresh-data path,总共只用了四个 CPU 核心。

让数据保持可查询 - ClickHouse Cloud

当这两个接入节点中的某一个 刷写其异步插入缓冲区时,它会按目标 MergeTree 表的 (sym, t) 排序键对事件级行排序,并写下一个有序的 data part。

同一节点还会并行在内存中对该块执行 incremental MV 的查询,计算聚合状态,再按目标 AggregatingMergeTree 表 的 (sym, day) 排序键对结果行排序,并写下一个包含预聚合数据的有序 part。

后台合并 会合并两张表中的 parts。两条写入路径处理同一个已刷写的插入块;排序和预聚合都在接入过程中完成,没有单独的刷新周期。

结果:原始数据和预聚合保持同步。 两者都从同一个已刷写的插入块向前推进;它们之间没有单独的刷新周期。

现在我们沿同样的两个阶段来看 Snowflake,其中数据接入和物化视图刷新被拆到不同服务里。

接入数据流 - Snowflake

该基准测试采用了 Snowpipe Streaming 的高性能架构,在应用写入与 Interactive Table 之间放置了一个服务端托管的数据摄取缓冲区。

Keeping data query-ready - Snowflake

Snowpipe Streaming 将数据行直接写入 Interactive Table。开启 CLUSTER_AT_INGEST_TIME=TRUE 后,它会在写入 micro-partitions(Snowflake 的列式存储单元)之前,先按共同的 (sym, t) 键对接入的数据行做预聚类。

Interactive Table 在存储上有取舍。在早前的研究中,数据量约为 1130 亿行时,Snowflake 的原始 Interactive Table 占用 2.9 TiB,而它的标准表为 701 GiB,ClickHouse 的原始表为 362 GiB------分别是后两者的约四倍和八倍。这些数据来自早前的配置。

另有一项由 Snowflake 托管的无服务器服务,会从该表异步刷新 Interactive MV。我们为该视图配置了 (sym, day) 聚类键,与 ClickHouse 预聚合表的排序键一致。刷新何时运行、消耗多少算力,都由 Snowflake 决定;用户既无法配置刷新计划,也不能调整刷新算力的规模。

结果:原始数据和预聚合可能不同步。 Interactive Table 通过摄取推进,而 Interactive MV 则通过另一套异步刷新周期推进。

深入底层:让两套系统同时达到每秒 100 万行

共用客户端与速率控制

两个目标端使用相同的 Parquet 数据源、行解码器、客户端计算、限速逻辑和八工作线程并行机制。共用的速率控制器将数据流控制在每秒 100 万行。只有投递适配器和目标端各自的批处理方式不同。

CLICKHOUSE CLOUD

客户端通过异步插入发送每批 3,000 行。每个接收节点将这些请求积累在服务端缓冲区中。

本次基准测试保留了运行时使用的默认缓冲设置。当以下三个阈值中任一条件率先满足时触发一次刷写:缓冲达到 100 MiB、自适应超时介于 50 毫秒到 1 秒之间,或排队插入查询达到 450 条。

SNOWFLAKE

客户端通过每个工作线程一个 Snowpipe Streaming 通道调用 append_row。SDK 选择了文件模式,将这些逐行调用在客户端分组为平均约 61,500 行的 NDJSON 批次。

跨八个通道,这产生了大约每秒 14.6 次文件上传。随后 Snowpipe Streaming 在服务端再次缓冲上传的批次,然后才提交其中的行。

如何理解这些批次大小

3,000 行和约 61,500 行这两个数字描述的是客户端投递批次。两套系统都执行了进一步的服务端缓冲,因此这两个数字都不能直接说明最终存储写入的大小。

查询服务架构

读端接收到的,正是这些不同的查询就绪状态。ClickHouse Cloud 用一个 16 核 CPU 的读服务同时承载两类工作负载;Snowflake 则使用配置大致相当的 Small Interactive Warehouse,并在其外围单独处理编译和回退。

读端计算 - ClickHouse Cloud

规格: 读服务使用一个节点,16 个 CPU、64 GiB 内存,与 Snowflake Small warehouse 的估算 CPU 数相当。

服务模式: 同一个服务处理两类工作负载。聚合查询读取始终最新的 AggregatingMergeTree 表,它与原始 MergeTree 表按相同的已刷盘插入块推进;因此当前答案在查询时无需再做任何对账。下钻查询读取事件级 MergeTree 表。

相同的路径也要经过 Snowflake 的服务层,它在 Interactive Warehouse 之外增加了编译和回退逻辑。

读端计算 - Snowflake

规格估算: Snowflake 不公开仓库的 CPU 和内存规格。我们借助 SELECT.dev 以及一份独立的 Gen2 分析,估算 Small Interactive Warehouse 约为 16 个 CPU,与 ClickHouse Cloud 的 16-CPU 读取服务相当;Snowflake 官方文档指出,该规格配有约 600 GB 的本地 SSD 缓存。

服务模型: Interactive Warehouse 是两个负载共用的主要服务。聚合查询指向 Interactive MV。如前所述,Snowflake 以异步方式刷新该视图,因此它可能落后于 Interactive Table。为返回最新结果,Snowflake 在查询编译阶段、执行尚未下发到仓库之前,通过其 Cloud Services 层对未刷新的基础表增量进行对账。下钻查询则直接读取 Interactive Table。

超时与降级: Interactive Warehouse 会取消超过五秒的查询,且该上限只能调低。我们另配了一个 Gen2 Small 标准仓库(同样估算为 16 CPU),通过 Snowflake 的自动降级机制接收符合条件的超时查询。

查询就绪度跟得上数据写入吗?

下图展示了在持续写入期间,预聚合数据落后各系统事件级表多少。数值越低,说明预聚合越接近最新写入的数据。

ClickHouse Cloud: 增量 MV 在插入过程中即处理每个刷盘的插入块,因此原始 MergeTree 与预聚合 AggregatingMergeTree 同步推进,全程原始数据到预聚合数据零延迟。

Snowflake: Snowpipe Streaming 让 Interactive Table 持续更新,但独立的无服务器刷新使 Interactive MV 落后。其活跃写入期的延迟平均为 1.4 分钟,峰值达 2.0 分钟,因此要得到当前聚合结果,必须在查询时做对账。

测量细节:新鲜度

SNOWFLAKE 延迟序列

MV 延迟序列使用了 2,072 个活跃的一分钟 behind_by 采样。轮询时间戳通过在 208 次活跃仪表盘观测之间做线性插值,与原始行数对齐。

报告的平均值和最大值来自居中的 61 个采样滚动均值。展示的趋势还叠加了居中的 11 个采样滚动均值和保形插值。由此得到的平均值 1.372 分钟、最大值 2.033 分钟在正文中四舍五入为 1.4 和 2.0 分钟。交互读数按所选行数跟随展示的趋势。

CLICKHOUSE 基线

ClickHouse 的 zero line 是基准语义基线,而不是单独轮询的提供商指标。原始表和增量 MV消费同一个已刷写的插入块,因此它们之间没有独立的刷新间隔。

查询就绪落后时发生了什么?

在摄取期间,两个系统各有 906 次匹配的查询执行,ClickHouse Cloud 累计查询运行时间为 61.8 秒 。Snowflake 累计 2.13 小时 ------约为前者的 124 倍。

图表显示,随着摄取推进,聚合查询和下钻查询的合计运行时间如何累积。

Snowflake 累计运行时间的大部分来自对其 Interactive MV 的聚合查询。我们先考察这条路径,再转向下钻查询------它们直接读取事件级数据,并暴露出另一个瓶颈。

测量细节:查询结果如何比较

完整查询定义,以及新摄取的数据如何影响其结果,见第 1 部分:在持续负载下测量每美元实时性能:CostBench 的首个端到端结果。

缓存策略

两个系统都禁用了查询结果缓存,因此每个被测量的查询都实际执行了。它们底层的数据缓存保持预热状态;数据缓存预热后,查询本身仍需运行。

读取端规格

ClickHouse Cloud 使用一个 16 CPU 的读取节点。Snowflake 使用一个 Small Interactive Warehouse 和一个 Gen2 Small 备用仓库,两者估计各约 16 CPU。该规格依据适用于下文的查询比较。

查询计时

查询延迟和累计运行时间采用每条记录查询完整的客户端可见时长。编译和执行图表显示 Snowflake 单独报告的阶段计时。其总和可能与客户端可见延迟不同;阶段图表说明时间花在哪里,但不替代用于运行时间和成本的端到端计时。

逐查询图表

延迟图表以各系统自身观测到的行数为横轴,一直绘制到 1000 亿行这一里程碑,既不按迭代次数对齐,也不在系统之间做插值。聚合查询的趋势(包括直接用原始表的方案)采用居中七点滑动中位数,下钻查询的趋势采用居中五点滑动中位数。

聚合图表仍沿用仅针对 Snowflake 的 Tukey 上界规则;被排除的点仍保留在其源数据和摘要中。下钻图表不做离群值过滤。

阶段图表则在累计编译边界和累计执行边界上,分别采用对应的七点或五点平滑。

如何阅读交互式图表

延迟对比默认以对数刻度打开,这样毫秒级和秒级数值可以同时看清。要比较绝对差值,请选择线性刻度。

延迟图表和阶段图表下方的读数,对应所选行数处显示的趋势。文中的中位数、P99、最大值和百分比数字,均概括其各自标注的测量窗口。

每个图表都有独立的播放控件和行位置控件。

累计运行时间与查询成本

运行时间和归一化查询成本采用已确认的按行数匹配的活跃摄入数据集:每个系统包含 209 个四查询聚合批次和 35 个两查询下钻批次,合计每个系统 906 次查询执行。观测值按摄入进度匹配。首个完整数据集的观测仍属于活跃摄入阶段,其后摄入完成后的观测不计入。

累计运行时间图表在这些匹配的行位置上累加上述记录的时长,观测值之间不做平滑,也不插值。其聚合部分对应维护预聚合的工作负载;后文考察的原始表方案属于另一项对比。

显示的时间是查询耗时之和。查询运行期间,数据摄取持续了数小时。

对预聚合数据执行聚合查询

在数据活跃摄取期间,基准测试每 10 分钟针对维护中的每日预聚合运行四个聚合查询(A1-A4)。这些汇总已包含所需计数、求和以及价格最小值和最大值,可用于计算截至当时已摄取历史数据中的股市活动。查询会按天或按股票组合这些预计算结果。查询结果必须包含新到达的行情,因此预聚合一旦滞后,查询引擎就仍有工作要处理。A1 和 A2 还会按股票代码过滤------股票代码是首要的排序键或聚簇列------因此可以跳过其他股票的汇总数据。

图表随数据集增长跟踪这四个聚合查询。ClickHouse Cloud 显示为黄色,Snowflake 为蓝色。启用 Show backup warehouse activity 可显示五秒阈值,并将 Snowflake 延迟趋势中高于该阈值的部分标为紫色。

ClickHouse Cloud: 在整个 1000 亿行图表窗口内,聚合查询延迟为:

• 中位数 13 ms - 比 Snowflake 快 801 倍

• P99 42 ms - 比 Snowflake 快 533 倍

• 最大值 111 ms - 比 Snowflake 快 218 倍

其增量 MV 作为插入路径的一部分,使聚合状态保持最新,因此查询无需对账。在 209 个行数匹配的活跃摄取批次 中,累计运行时间为 11.36 秒。

Snowflake: 在同一图表窗口内,聚合查询延迟为:

• 中位数 10.41 秒 - 比 ClickHouse Cloud 慢 801 倍

• P99 22.20 秒 - 比 ClickHouse Cloud 慢 533 倍

• 最大值 24.17 秒 - 比 ClickHouse Cloud 慢 218 倍

查询将滞后的 Interactive MV 与 Interactive Table 中较新的行做归并,增量不断累积、刷新又将其削减,于是形成了锯齿状模式。在上述同样 209 个匹配批次中,累计运行时间为 2.11 小时 ;按此前采纳的 5 秒回退代理口径,836 次执行中有 477 次------57% 越过阈值,被归入回退路径。

在交互式聚合查询负载上,ClickHouse Cloud 比 Snowflake 快 669 倍,而且预聚合数据始终保持最新,无需在查询时再做归并。

未完成的刷新工作会在查询编译阶段重新出现

Snowflake 报告的阶段耗时说明了聚合查询把时间花在了哪里。橙色代表编译,蓝色代表仓库执行。

本图涵盖的各项观测中,编译占所报告阶段总耗时的 85% ,仓库执行占 15%。追加仓库计算资源,作用的只是执行那部分;而主导这些查询的编译工作,运行在 Snowflake 单独管理的 Cloud Services 层。

橙色编译区域不是花钱就能买掉的------能买到的只有那条细细的蓝色执行带。

下图说明了原因。

① 聚合查询通过 Interactive Warehouse 访问 Interactive MV。尽管视图落后于最新数据,查询仍必须返回当前结果,包括在上次刷新之后才到达的行。

② 在查询编译 阶段,Snowflake 的 planner 要决定如何把物化视图与这些更新的行结合起来。为此,它需要加载自上次刷新以来创建的每一个基表 micro-partition 的元数据。这部分编译在 Snowflake 共享的 Cloud Services 层 完成,之后才在仓库中开始执行。

这部分编译工作的资源由 Snowflake 管理,用户无法调整规格。加大仓库规格,只是为后续执行阶段增加资源。

随着刷新之间新的微分区不断累积,每次查询在编译阶段要处理的元数据也随之增加。当刷新追上进度时,这部分工作量缩小,延迟下降,随后又随着数据摄入的持续而重新攀升。

悖论在于:更快的 Snowpipe Streaming 反而让当前 MV 查询更慢。 异步刷新之间累积了更多新的微分区,每次查询因此继承更多对账工作。

深入底层:对账、仓库规模与回退

1. 查询的两个阶段

每条 Snowflake 聚合查询都先在共享的 Cloud Services 中编译,与仓库无关,然后在选定的仓库上执行。

2. Snowflake 如何组装当前 MV 的答案

当 Interactive MV 落后时,Snowflake 不会返回过期结果。编译期间,规划器会将视图与自上次刷新以来加入 Interactive Table 的所有内容进行对账,为此加载该增量中每个新基表微分区的元数据。

3. 延迟为何先升后降

无服务器 MV 刷新异步运行时,Snowpipe Streaming 仍在不断创建微分区。未刷新的增量在两次刷新之间增长,刷新追上后缩小,于是形成了与延迟曲线中相同的先升后降模式。

4. 我们的测量结果

编译占 Snowflake 聚合查询时间的 85%,仓库执行占 15%。在以五秒回退为判定标准的情况下,836 次执行中有 477 次------即 57%------进入了归因于回退的路径。

5. 为什么扩大仓库规模或使用回退仓库都无法消除瓶颈

仓库规模只改变执行侧的计算资源。在查询到达 Interactive Warehouse 或 Gen2 Small 回退仓库之前,对账已经在共享的 Cloud Services 中完成了。

6. 该机制的早期诊断证据

一次剖析的查询中,远程 micro-partition 元数据 I/O 在 5,030 ms 的编译阶段里占用了 4,908 ms,达 97.6%,平均每个分区约 25 ms。另有一项 Small 与 X-Large 的对比诊断,覆盖约 4 亿至 168 亿原始行,结果显示 X-Large 并未改善编译耗时,尽管其 credit 费率高 8 倍。这些诊断解释了机制;上文的核心数据来自 Run14。

7. 成本影响

等待编译期间,仓库仍然活跃并持续计费;而当每日 Cloud Services 用量超过仓库日用量的 10% 时,Cloud Services 用量本身也会开始计费。因此,摄入越快,对账延迟越长,潜在成本也越高。

8. 如何解读回退标记的颜色

启用 Show backup warehouse activity 后,紫色标出 Snowflake 平滑延迟趋势中超过五秒的部分。

回退次数与归一化成本分摊是单独计算的,与每条查询的实测耗时无关。超过五秒的查询,按 Gen2 Small 费率对其全部耗时计费;五秒及以下的查询,按 Interactive Small 费率计费。每条查询只归入一个计费档。

高亮与计费规则采用的是耗时代理指标,无法确定每条查询实际由哪个仓库执行。

这种代理可能漏掉五秒及以下发生的回退。后文的评分框给出了完整的计费边界与排除项。

针对事件级数据的下钻查询

在数据摄入活跃期间,基准测试每小时直接对事件级表运行两个下钻查询(D1-D2)。它们按小时汇总价格,并针对某只股票不断增长的历史数据计算风险与流动性画像。查询结果必须包含新到达的报价,因此事件级表要让新行始终可查,数据布局也要支持高效过滤。两个查询都按股票代码过滤,该字段是各表排序键或聚簇键的首列。

图表跟踪这两个下钻查询随事件级表增长的表现。ClickHouse Cloud 为黄色,Snowflake 为蓝色。

这些查询绕过了 MV,直接读取各张事件级表,因此这条路径隔离出来的是事件级布局与查询服务本身,而非 MV 与底层数据的一致性对齐。两个系统都采用相同的 (sym, t) 排序/聚簇方式,读取侧算力约为 16 个 CPU;Snowflake 的 Small Interactive Warehouse 还额外提供了约 600 GB 的本地 SSD 缓存。

ClickHouse Cloud: 在千亿行数据对应的图表窗口内,下钻延迟为:

• 中位数 722.5 ms --- 比 Snowflake 快 1.38 倍

• P99 1.15 s --- 比 Snowflake 快 2.06 倍

• 最大值 1.18 s --- 比 Snowflake 快 2.17 倍

在 35 个行数匹配的活跃写入批次中,累计运行时长为 50.47 秒。有序 MergeTree 路径的延迟增长更平缓,在数据量更大时依然保持更低。

Snowflake: 在同一个图表窗口内,下钻延迟为:

• 中位数 993.5 ms --- 比 ClickHouse Cloud 慢 1.38 倍

• P99 2.37 s --- 比 ClickHouse Cloud 慢 2.06 倍

• 最大值 2.56 s --- 比 ClickHouse Cloud 慢 2.17 倍

在同一批 35 个匹配批次中,累计运行时长为 74.81 秒 。尽管 Interactive Warehouse 配有约 600 GB 的本地 SSD 缓存,延迟随着数据累积上升得更陡;全部 70 次执行都低于 5 秒的降级回退阈值。

在这组行数匹配的下钻负载中,ClickHouse Cloud 整体快 1.48 倍,而 Snowflake 还额外有约 600 GB 的本地 SSD 缓存。

事件级表不断增长,留给查询执行的工作更多

在图表覆盖的测量窗口内,Snowflake 上报的下钻阶段耗时中,仓库执行占了主要部分。

Snowflake 的阶段遥测显示,瓶颈与 MV 路径不同。中位数下,D1 的编译耗时 225 ms ,D2 为 191 ms ;执行耗时分别为 643 ms 和 830 ms ------占提供商报告阶段时间的 74--81%。这部分执行开销随着 Interactive Warehouse 读取并过滤不断增长的事件级表而增加。与 MV 对账不同,它在仓库内部运行,可以通过增加仓库算力来降低。

下钻查询的主要瓶颈在"执行":换更大的仓库就能减少这部分耗时。 而独立的编译环节依然在仓库之外。

深入分析:缓存跟上了。这要怎么扩展?

实测案例

Snowflake 官方文档将 Interactive Warehouse 缓存预热 描述为非阻塞的后台过程。在此工作负载更早的一次诊断运行中,查询 profile 显示,在持续写入期间,远程读取为零或可忽略,中位数下 100% 的字节由缓存提供。

在约 75 MB/s 的写入速率下,查询工作集能装进 Small 仓库约 600 GB 的缓存,预热也把相关数据保持在本地。这些诊断解释了缓存的行为;Run14 提供了上面那些关键延迟数据。

这说明了什么

这是缓存表现理想的场景:工作集装得下,预热跟得上。剩下的延迟主要来自在持续增长的事件级表上执行扫描和过滤,而不是反复从远程存储拉取工作集。

边界 1:工作集容量

即便是最大的 Interactive Warehouse------4X-Large------缓存也有上限,为 44 TB。一旦查询的工作集超出缓存,更多读取就会转向远程。仓库选小了,延迟会逼近五秒上限,超时的查询会被转到 fallback;选大了,又要为用不上的缓存付费。

边界 2:预热吞吐

Snowflake 官方文档给出的缓存预热吞吐约为 即使是 X-Small 仓库也能达到 300--400 MB/s,并称仓库越大预热越快。文档中这个 X-Small 速率明显高于本基准测试约 75 MB/s 的写入速率。

但当源端速率更高时,与查询相关的数据到达的速度可能快过预热把它变成本地数据的速度:整个工作集或许仍能装下,只是最新写入的那些行需要走远程读取。

容量规划的含义

Snowflake 客户在为 Interactive Warehouse 选型时,既要看查询会触及多少数据,也要看新数据到达有多快。ClickHouse 的查询直接跑在有序的 MergeTree 表上,无需单独填充一份服务缓存来规划容量或维持预热。

绕过 MV,聚合就落到了原始表上

这条事件级路径也提供了一个有用的对照组:

如果 Snowflake 的聚合查询绕过滞后的 MV,直接跑在原始 Interactive Table 上,会怎样?

这里比较的是 Snowflake 对原始 Interactive Table 的聚合查询与 ClickHouse Cloud 对当前预聚合的查询,读取侧容量配置与前面相同。启用 Show backup warehouse activity,即可显示 5 秒阈值线,并用紫色标出 Snowflake 高于阈值的延迟走势。

ClickHouse Cloud: 预聚合路径与结果同前。

Snowflake: 绕过 Interactive MV、直接查询原始 Interactive Table,结果为:

指标 原始表延迟 对比 Interactive MV 对比 ClickHouse Cloud
中位数 2.47 s 快 4.21× 慢 190×
P99 18.04 s 快 1.23× 慢 433×
最大值 20.67 s 快 1.17× 慢 186×

绕过滞后的 Interactive MV,省去了查询时的对账,但聚合工作依然留在 Snowflake 的原始表上。A1 和 A2 都按 sym------也就是聚类键的首列------做过滤,可二者都随着 Interactive Table 增长呈现出明显的延迟上升趋势。在测量窗口内,即便走这些选择性较高的路径,写入的数据越多,查询时的计算量也越大。而在同一个 1000 亿行的窗口内,ClickHouse Cloud 的预聚合延迟基本保持平稳。

A3 和 A4 都是未经过滤的全表聚合。按约定采用的五秒兜底代理口径,836 次执行中有 220 次、占 26% 越过阈值,被归到兜底路径:A3 执行 103 次 ,A4 执行 117 次 。在同样匹配的 209 个批次里,Snowflake 的原始表路径累计运行 1.10 小时。

绕过滞后于数据的 Interactive MV 省掉了查询时的对账,Snowflake 因此变快 ------但聚合工作被转移到了原始表上。在匹配的工作负载中,ClickHouse Cloud 那条本就保持最新的预聚合路径仍然快 347×。

在 Snowflake 的两条聚合路径上,新鲜数据路径没做完的工作都会在查询时重新冒出来:

• Interactive MV: 查询编译期间的对账,解释了预聚合中缺失的行。

• Raw Interactive Table: 查询执行期间的扫描与聚合,直接从事件级行算出答案。

ClickHouse Cloud 在写入时完成预聚合,最新汇总随时可供查询。

剩下最后一个架构问题:Snowflake 能否用一种查询很快的形式,存下最新的预聚合结果?

为什么 Snowflake 的查询就绪路径必然要在新鲜度和延迟之间取舍

两组聚合测试暴露出一个结构性选择。查询 Interactive MV 能返回当前结果,但 Snowflake 必须在编译阶段对尚未刷新的增量做对账。查询原始 Interactive Table 可以避开这次对账,却也丢掉了预聚合,把工作变成了对一张不断增长的表做扫描和聚合。

最自然的组合方式并不被支持

最自然的替代方案,是把预聚合结果存进一张自动刷新的 Interactive Table,让聚合查询变成普通的表读取。这样得到的是异步刷新的结果,而支持的最小目标滞后为一分钟。

即便有这种新鲜度上的取舍,直接组合依然不被支持:Snowpipe Streaming 的高性能路径会把原始数据写入一张 Interactive Table,而 Snowflake 不支持把一张 Interactive Table 当作另一张 Interactive Table 的自动刷新源。

接收流的组件,无法为让预聚合保持快速的组件供数。

受支持的路线是条绕路

受支持的路线先把流写入一张标准表,再用一个刷新仓库分别维护原始表和预聚合的 Interactive Table。这样会多出一份原始数据副本,还需要专门的刷新算力。一分钟的最低目标延迟要求依然适用。

下表只是大致划定对比范围,并非严格的三方重跑:前两行复用本文的结果,受支持绕路那一行则是对此前研究的概括,数据量到 1000 亿行。三条路径的读侧算力都在约 16 个 CPU;受支持的绕路还要额外用到上图那个独立的 128 CPU Gen2 X-Large 刷新仓库。

摄入期间的聚合查询延迟与新鲜度

新鲜数据路径 查询延迟中位数 P99 查询延迟 最大查询延迟 结果状态 / 刷新开销
ClickHouse Cloud · 增量物化视图 13 ms 42 ms 111 ms 设计上即为最新
Snowflake · 交互式物化视图 10.41 s 22.20 s 24.17 s 通过查询时对账保持最新
Snowflake · 受支持的变通方案(此前研究) 173 ms 557 ms 925 ms 并非持续最新:最低目标延迟 1 分钟;截至 1000 亿行,刷新仓库额外支出 +$1,814.40

中位数口径下,受支持的变通方案比 Snowflake 的交互式物化视图快约 60 倍,但仍比 ClickHouse Cloud 慢约 13 倍。 它还增加了 1,814.40** 的刷新仓库成本,而这只是跑到 1000 亿行;相比之下,下文展示的 ClickHouse Cloud 完整新鲜数据路径,在完整的 1132 亿行数据接入全程只花 **28.69。

Snowflake 的取舍:要么结果最新,要么聚合查询始终快速。

• 交互式物化视图: 结果最新,但对账拖慢了查询编译。

• 原始交互式表: 结果最新,但每次查询都得扫描并聚合不断增长的原始数据。

• 受支持的变通方案: 查询快,但基于异步刷新的预聚合,且需要单独的刷新仓库,最低目标延迟为 1 分钟。

ClickHouse Cloud 两者兼得: 预聚合保持最新,聚合查询也快,准备工作在数据接入时完成。

受支持的变通方案需要什么?

结果契约

受支持的变通方案查询的是一张异步刷新的预聚合表,而不是在查询时对账出当前结果。它支持的最低目标延迟为 1 分钟。

刷新容量与成本

在该模拟的 1000 亿行场景中,一个 Gen2 X-Large 刷新仓库连续运行 28 小时,按 Enterprise 标价(21.6 信用点/小时 × 28 小时 × 3/信用点)计,增加了 **1,814.40**。

更小的仓库

Gen2 Small、Medium 和 Large 分别在约 3、8、15 小时 后不再满足一分钟目标。X-Large 在前 24 小时内保持了这一目标,但延迟仍在上升。

最后一点范围说明:下面的评分涵盖本文测试的架构------将 Snowpipe Streaming 写入 Interactive Table,并在 Interactive MV 中维护预聚合。上面提到的受支持的标准表替代方案不属于本次比较;我们在上一篇博文中对其成本与性能做了基准测试。

最终结果:每美元实时性能

第 1 部分完整定义了 CostBench 评分模型。简而言之,CostBench 将保持数据集可查询的成本,与服务查询工作负载的标准化成本相加,再将该合计成本乘以工作负载累计的端到端运行时间。数值越低越好。

Snowflake 的端到端评分差了 412 倍

下方图示展示了三个评分输入项和最终的 412 倍结果。展开可查看源数据、完整公式、匹配边界和 Snowflake 回退假设的定价细节。

评分沿用相同的大致匹配的 16-CPU 查询服务基准:ClickHouse Cloud 使用一个 16-CPU 读节点,而 Snowflake 的 Small 查询仓库估计约为 16 CPU。它另外单独计入每个系统完整的新数据路径成本。

端到端评分:定价、公式和计算边界

定价基础

AWS us-east 的企业版定价为每个 Snowflake credit 3 美元,每个 ClickHouse Cloud 计算单元 (CU) 每小时 0.3903 美元。Snowflake 的无服务器费用直接来自其计量历史。

① 新数据路径成本

这涵盖完整的 1132 亿行数据摄入。

ClickHouse Cloud

2 CUs × 36.75 小时 × 0.3903/CU-小时 = 28.68705。

Snowflake

Snowpipe Streaming 处理了 4.6762 TiB 数据,按 Snowflake 的每未压缩 GB 0.0037 credits 费率计费,共 17.71783 credits。按未取整的计量值计算:显示值 17.71783 credits × 3/credit = 53.15348。

Serverless MV 刷新计费 8.75553 credits。8.75553 credits × 3/credit = 26.26659。

合计:53.15348 + 26.26659 = $79.42007。 写入时聚簇已包含在 Snowpipe Streaming 中;没有使用写入仓库。

② 归一化查询服务成本

CostBench 对每条匹配的活跃写入期查询,都按完整端到端运行时长 × 适用的每秒读侧费率计价。匹配的调度中,每个系统有 209 × 4 = 836 次聚合执行、35 × 2 = 70 次下钻执行。

ClickHouse Cloud

8 CUs × 0.3903/CU-小时 ×(聚合 11.361s + 下钻 50.466s)÷ 3,600 = 0.05362。

Snowflake

按 Interactive 计价的时间:(聚合 946.509s + 下钻 74.815s)× 1.2 credits/小时 × 3/credit ÷ 3,600 = 1.02132。

按 fallback 计价的时间:聚合 6,653.660s × 2.7 credits/小时 × 3/credit ÷ 3,600 = 14.97074。

合计:1.02132 + 14.97074 = $15.99207。

所采用的近似计价方式为:五秒及以内的作业按 Interactive Small 计价,超过五秒的作业按其在 Gen2 Small 上的完整耗时计价。836 个聚合作业中有 477 个(57.1%)超过该阈值;下钻作业无一超过。编译时间已计入。

常备的 fallback 容量、最低计费,以及按 fallback 价格计费的作业额外产生的主仓库费用,均不计入。

③ 查询总运行时长

ClickHouse Cloud:11.361s 聚合 + 50.466s 下钻 = 61.827s。

Snowflake:7,600.169s 聚合 + 74.815s 下钻 = 7,674.984s。

计算边界

① 覆盖完整的写入过程。② 和 ③ 只采用活跃写入阶段、行数匹配的观测值;写入完成后的观测数据不计入。

存储不计入。数据库存储成本不纳入评分,所以 412× 这个结果不包含前文讨论的存储占用差异。显示值可能经过四舍五入,但评分使用全精度输入。

最终得分

ClickHouse Cloud:(28.68705 + 0.05362) × 61.827 = 1,776.9494。

Snowflake:(79.42007 + 15.99207) × 7,674.984 = 732,286.6479。

相对结果:732,286.6479 ÷ 1,776.9494 = 412.103×。

精确汇总 公布了每一项被采纳的输入,以及归一化成本的计算约定。

前文给出的 124× 累计运行时长差距 ,现在与 3.32× 的端到端成本差距 合并计算。CostBench 将这两个维度相乘,得到 412× 的端到端得分差距。

Snowflake 的新鲜数据链路影响了每一项得分输入: Snowpipe Streaming 和 MV 刷新带来直接成本;对账拉长了查询总运行时长;而运行时长增加又推高了归一化后的查询服务成本。

实时性价比差距从何而来

最后的对比把两个维度放在一起。在实测终点上,ClickHouse Cloud 是 61.8 秒累计查询运行时长加 28.74 端到端成本** ,而 Snowflake 是 **2.13 小时和 95.41。

ClickHouse Cloud 的优势始于一套简洁的一体化架构。数据摄入、排序和预聚合都内建在存储引擎里。原始数据与汇总数据同步推进,不需要单独的刷新服务或刷新周期。查询读取的是当前已就绪的数据,没有尚未完成的准备工作要追补。

Snowflake 经过验证的流式路径把摄入与预聚合拆开。它的原始表不断推进,汇总数据却落在后面。要返回当前的答案,查询就得自己补齐差距,带来额外的延迟和成本。

这些变通改变了取舍。直接查原始数据保住了新鲜度,却要重复做聚合运算;用单独刷新的汇总数据来服务查询,读取更快,但放弃了持续的新鲜度,还增加了基础设施和成本。

这些架构差异在结果中清晰可见。持续摄入到 1000 亿行的过程中,ClickHouse Cloud 的交互式聚合查询 P99 延迟为 42 毫秒 ,而 Snowflake 的 Interactive MV 路径为 22.20 秒。

同一套架构也让新鲜数据这条路径保持了经济性。更低的准备成本,加上更快的查询服务,在这个基准测试中共同带来了每美元端到端实时性能 412 倍的提升。

ClickHouse Cloud 从端到端都是为在持续更新的数据上快速给出答案而专门构建的。它的优势来自整套系统的协同运作------从准备每一行新到的数据,到给出当前的答案。

关于我们

ClickHouse(clickhouse.com) 是面向 AI 时代打造的高性能实时分析数据库,能够以极致性能处理海量数据分析任务。凭借高并发、低延迟和云原生架构,ClickHouse 广泛应用于可观测性、数据仓库、实时分析及 AI 数据基础设施等场景。我们致力于帮助企业在公有云平台上构建安全、弹性且高性价比的实时分析与 AI 数据平台,加速释放数据价值,推动智能化创新与数字化转型。目前,Trip.com、DiDi、Meta、Sony、Netflix、Deutsche Bank、Sierra、Cloudflare 等全球领先企业均在使用 ClickHouse 支撑其关键业务和数据分析平台。

相关推荐
m0_639906942 小时前
Redis入门|五种数据结构、使用场景、持久化RDB&AOF
数据结构·数据库·redis
欧米欧2 小时前
Linux系统篇(七),环境变量的底层溯源,核心获取机制与安全应用
linux·运维·服务器
Ruiery2 小时前
Linux 6.6内核内存管理深度解析(十八):KASLR 内核地址空间随机化
linux·运维·服务器·安全
todoitbo3 小时前
群晖NAS部署JmalCloud:Docker安装、文件管理、博客与公网访问完整教程
运维·docker·容器
时间售卖铺3 小时前
触发器与函数实战:MySQL高效编程秘诀
运维·数据库·mysql·云原生
qetfw3 小时前
UOS MariaDB 数据库:安装、最小权限与备份验证
linux·数据库·mariadb·uos
前端精髓3 小时前
调用大模型API
运维·服务器·microsoft
跨境小彭4 小时前
Temu 全托管模式下,SKU 利润核算的实践复盘
大数据·运维·人工智能·自动化·temu
李纲明4 小时前
WordPress 定时发布不跑、备份邮件延误:先核 WP-Cron 触发与回环,再改系统 Cron
运维·wordpress·定时任务·devdiy·wp-cron