☰
CostBench 首批端到端结果:持续负载下四家云数据仓库的每美元实时性能对比
2026/10/28 18:54:28 网站建设 项目流程

本文字数:9305;估计阅读时间:24分钟

作者:Tom Schreiber and Lionel Palacin

编者按:本文译自 ClickHouse 原博客(链接点文末-查看原文)。 原文围绕「以持续负载下的端到端成本口径重新衡量实时分析系统的每美元性能」展开。把写入路径成本与查询成本放在同一工作负载中考察,比单看查询延迟或单价更接近真实生产账本。首批结果给出的倍数差距较大,后续一对一拆解值得关注其计费与架构归因是否可复现。

TL;DR

每美元能换来多少实时性能,既取决于让新到数据保持可查询状态的成本,也取决于这项准备工作给查询引擎留下多少活。

• CostBench 把这两方面合并成持续负载下的一个连续工作负载来衡量:聚合查询和下钻查询持续运行的同时,新行不断写入并变为可查询状态。

• 我们按照各厂商推荐的实时写入路径,测试了 ClickHouse Cloud、Snowflake、BigQuery 和 Redshift Serverless,以每秒 100 万行的目标速率流式写入超过 1000 亿条股票行情数据。

• ClickHouse Cloud 的新数据路径成本、查询服务成本和累计运行时间都是最低的。参与测试的其他方案, 端到端每美元性能差了 412–1,996 倍。

• 这篇文章开启了一系列一对一分析,逐一追溯这些结果背后的架构与计费逻辑。

从新数据到快速查询的这条路径,决定了每美元的性能

实时分析系统要在不断变化的数据集上提供查询服务。新行持续涌入,而用户、应用和智能体同时在查询可能已达数十亿乃至数万亿行的数据。每一条新行都必须变为可查询状态,同时这些查询还要继续跑。

CostBench 衡量各云数据仓库上实时分析的端到端性能与成本。首批结果说明,查询引擎只是这些系统之间差异的一部分:

在把新到数据从抵达带到可查询的这段过程中,各系统的成本与效率差异极大。

在持续负载下,这部分工作对每美元性能的影响不亚于查询执行本身:它自身产生直接成本,而它留下的数据状态又决定了查询引擎还剩多少活要干。

第一轮端到端测试采用推送式写入,覆盖 ClickHouse Cloud、Snowflake、BigQuery 和 Redshift Serverless。

CostBench 测量了数据导入、持续的查询就绪工作,以及聚合查询和下钻查询服务——这些同时运行。这篇文章先解释查询就绪的含义,然后展示基准测试如何运作,并呈现总体结果。后续的 1:1 文章会通过每个提供商的架构和计费模型来追溯这些结果。

什么让数据查询就绪

考虑一个关于股票报价的常见分析问题:每天有多少条 AAPL 报价更新到达?

该查询筛选出 AAPL,按天分组其报价,并统计每组中的行数:

SELECT day, COUNT(*) FROM quotes WHERE sym = 'AAPL' GROUP BY day;

分析系统正是为快速运行这类查询而构建的。

查询就绪的数据经过组织和准备,使查询引擎在查询时读取更少数据、做更少工作。

对于我们的“每日 AAPL”查询,三个步骤帮助引擎读取更少数据并减少工作量。

按列存储数据

我们的查询需要Symbol来查找 AAPL 的报价,需要Day来分组。它不需要其他任何列。

列式存储 让引擎只读取那两列,跳过其余列。在下面的例子中,这意味着读取2 列而不是 7 列。

列式布局也有助于引擎处理它读取的数据。当一列的值在内存中放在一起时,引擎可以在一个简单循环中对一批值应用操作。这种向量化执行减少了逐行处理的开销。合适的操作还可以使用 SIMD 指令,用一条指令处理多个值。

组织数据以便分块裁剪

上述批次是连续列值的块。在读取一个存储数据块之前,引擎检查其元数据;当元数据表明该块不可能包含匹配查询筛选条件的值时,就跳过它。这就是分块裁剪。

我们的查询已经只读取Symbol和Day列。但在未排序的例子中,AAPL 报价出现在全部三个块中,因此引擎必须读取全部三个块。

排序 按Symbol将每只股票的报价放在一起。对于WHERE Symbol = 'AAPL',引擎现在读取一个 AAPL 块,跳过 MSFT 和 NVDA 块。这样就剩下三条 AAPL 报价,需要按天分组并计数。

预聚合减少查询时的工作量

当数据量达到数十亿甚至数万亿行时,扫描和聚合原始数据对交互式分析来说可能太慢了。而且这类查询往往会反复执行,比如在仪表盘中,计算成本还会不断累积。

预聚合把这项工作从每次查询中移出,提前到数据准备阶段完成。它维护一组小得多的汇总行,从而减少查询时需要读取的数据量,也减少分组和聚合的运算。这些汇总保留了查询所需的分组维度和聚合结果,让引擎可以直接合并预先准备好的结果,而不必从每一行原始数据重新计算。

在我们的例子中,裁剪之后剩下三条 AAPL 报价,需要按天分组并计数。预聚合提前算好了这些计数:按Symbol和Day分组,对每组计算COUNT(*)。这样就把九条报价变成了四行汇总数据,每行包含某只股票在某一天的计数。

由于查询仍可能对汇总行做过滤,预聚合数据同样受益于便于裁剪的物理布局。我们的汇总行按Symbol排序。对于WHERE Symbol = 'AAPL',引擎只读取两行 AAPL 汇总数据,跳过 MSFT 和 NVDA 的行。这两行已经包含了每日计数——D1 有两条报价,D2 有一条——因此引擎不再需要在每次执行时对单条 AAPL 报价进行分组和计数。

对于监控市场活动这类时效性强的场景,这些汇总必须与底层报价保持同步,最好能在新报价可查询时同步更新。

对于我们的 AAPL 查询,列式存储让引擎跳过无关字段,按Symbol排序让它跳过其他股票,实时的预聚合让它跳过对单条报价的分组和计数。这些准备工作共同让数据对这类分析查询即刻可用:查询引擎读取的数据更少,执行的计算也更少。

实时系统必须让新到达的数据即刻可查询

对于固定数据集,这种准备可以在查询开始前完成。在实时系统中,新行会持续到达,而查询仍在运行。

“实时系统应当能访问实时数据,这样才有可能基于最新鲜的数据做出实时决策。” — Instacart Engineering

我们把持续进行、让每一行新数据从到达走向可查询状态的工作称为新鲜数据路径。它包含三项必须并行保持运行的职责:

① 数据到达时,摄取新鲜数据并写入列式存储。

② 通过排序、聚簇、分区或等效结构,为事件级数据和预聚合数据维护便于裁剪的物理布局。

③ 新数据到达时,维护最新的预聚合结果,让常见的分组和聚合工作不必落在查询时执行。

这些是逻辑上的职责,而不是严格的执行顺序。系统可以把它们融合到一条写入路径中——例如,在把任何一种表示写入存储之前,先对传入行排序、计算预聚合,再对这些结果排序。另一些系统则在摄取完成后异步完成其中一部分工作。

索引、元数据、compaction 以及其他特定于提供方的结构,也会影响这项工作的成本和效率。

在新鲜数据路径之外,查询引擎还要服务两条典型的分析路径。两者都依赖上文所述的准备工作:

• 预聚合路径: 交互式聚合查询依赖 ③,让重复的分组和聚合不必发生在查询时。如果它们要过滤汇总后的行,还会依赖 ② 来裁剪无关数据块。

• 事件级路径: 选择性下钻查询直接读取事件级数据,因此依赖 ② 来避免扫描大部分数据。即使这类查询要花几秒,让它们在大规模下可行的关键仍是裁剪;它们仍可能对剩余行做分组或聚合。

高效的新鲜数据路径会降低自身成本——也减少留给查询的工作

系统可以维持摄取,即使查询就绪状态已经落后。

能跟上新数据的流入,并不保证系统跟得上高效查询这些数据所需的全部工作。

这一差距会影响答案新鲜度:新股票报价或许能及时写入,但风险查询仍可能依据过时的市场视图返回结果。

即使查询能看到最新数据,它也可能影响查询效率。如果排序或预聚合落后,查询引擎就可能需要扫描更多数据、归并较新的行,或在查询时重复做分组和聚合。

下方的交互图展示了第二种影响,此时数据仍在持续流入。观察循环播放,或拖动滑块,就能看到随着排序和预聚合逐步跟上,查询引擎的扫描与聚合工作量如何缩小;当数据准备落后时,它又如何增长。

这些额外的查询工作会消耗读侧计算资源,增加延迟和查询服务成本。因此,一条高效的新鲜数据路径能在两方面带来收益:准备数据的成本,以及它所服务查询的运行时间和成本。

CostBench 同时衡量两种影响

CostBench 跟踪同一份持续增长的数据集,涵盖从摄取、行可见性、事件级布局维护到预聚合新鲜度的全过程,同时聚合查询和下钻查询按固定时间表运行。查询定义保持不变,但其答案必须不断纳入新到达的数据。这让两方面都清晰可见:保持数据处于可查询状态的直接成本,以及从系统实际达到的状态出发服务查询时的性能与成本。

首批结果显示,有些系统在维持摄取的同时,预聚合滞后不断累积,或查询延迟上升——这会把更多工作移到读路径上,并推高查询服务成本。

CostBench 如何保持比较公平

本轮在ClickHouse Cloud、Snowflake、BigQuery和Redshift Serverless上使用了基于推送的摄取:一个共享客户端直接通过各系统推荐的低延迟摄取路径发送数据流。四项控制措施让比较保持同口径,同时尊重各系统的架构:

• 相同工作负载 :每个系统接收同一份 1132 亿行的全国最佳买卖报价(NBBO)股票行情数据集、相同的 schema、布局意图、每秒 100 万行的目标摄入速率、查询和节奏。

• 可比资源 :在能够进行有意义比较的地方,我们对读取端计算做了对齐,并采用经测试可配置的全新数据路径计算最小配置,该配置在校准期间能够维持目标速率。

• 完整平台路径 :每个系统都使用其推荐的实时架构,配备低延迟的推送式摄入路径。托管和无服务器服务保留其原生扩缩容能力,其计量工作量也计入基准测试成本。

• 统一测试框架 :相同的源文件、解码逻辑、客户端主机、速率控制器、调度器、计时和记录逻辑驱动每个系统;只有目标适配器不同。

我们在各系统之间为原始数据和每日预聚合配置了匹配的排序键或聚簇键。这些布局支持工作负载中的股票代码过滤。预聚合按股票代码和日期对报价分组,维护聚合查询所用的计数、求和以及价格最小值和最大值。因此,每个系统都必须在新行到达时,为相同的查询工作负载保持相同的预处理数据处于最新状态。

后续轮次还可能使用一个共享外部流测试拉取式变体,以更完整地呈现每美元实时性能。

共享测试框架保持工作负载恒定。CostBench 衡量每个系统如何处理它。

基准测试方法与公平性控制

摄入模型

客户端从 Parquet 文件读取 NBBO 数据,将其解码为原始行,然后通过各平台厂商推荐的低延迟实时摄入路径,将流直接推送到每个平台的目标表中。后续轮次将使用一个共享外部流测试拉取式变体。

工作负载模型

在实时分析系统中,新事件在源头按应用决定的速率持续产生。未来的行尚不存在,所以数据库拿到的从来不是一份完整的积压数据,可以慢慢按最快速度加载。CostBench 重现的正是这种运行条件:把 Parquet 文件当作确定性的数据源,解码其中的行,再以受控节奏作为连续流释放,同时各平台要让到达的数据始终可查询,并执行定时查询。

数据集与活跃窗口

每个系统都收到同一份完整数据集:1132 亿行、12 列的窄表,内容是全国最佳买卖报价(NBBO)股票行情。

所有系统都使用了以下排序键或聚簇键:

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

• 按日预聚合: (sym, day) ——股票代码与日期。

测试框架把整个数据源作为一条不间断的流回放,目标速率为每秒 100 万行,持续到最后一来源行写入为止。若严格按目标速率运行,这段活跃写入窗口将持续约 31.4 小时;实际观测到的时长因系统而异。

共用的写入客户端

同一批源文件、同一套 schema、同一份行解码逻辑和工作负载生成代码,驱动了 ClickHouse Cloud、Snowflake、BigQuery 和 Redshift Serverless。对每个系统而言,客户端都运行在同一台 AWS EC2 m6i.8xlarge 实例上,使用同一个速率控制器,并通过调整批大小和 worker 并行度,让目标端逐步逼近目标速率。

平台按最佳实践配置

唯一变化的是针对目标平台的投递适配器。在每个平台内部,我们都采用厂商推荐的低延迟 push 式实时写入路径,以及官方文档给出的、用于让新到数据保持可查询的最佳实践。这些路径之间的差异本身就是基准测试的一部分。

资源规格确定策略

在平台之间能够进行有意义比较的地方,我们按估算的 CPU 容量对齐读取侧算力。对于可配置的新数据路径算力,我们选用校准期间能维持每秒 100 万行目标速率、同时让新到数据保持可查询的最小测试配置。托管组件和无服务器组件使用其原生扩缩容能力,其按用量计费的工作量仍计入基准测试成本。实际观测到的端到端吞吐量与设定的目标速率分开报告。

共享查询驱动

从摄取开始到最后一个源数据行,同样的四个交互式聚合查询每 10 分钟运行一次,同样的两个选择性下钻查询每小时运行一次,采用完全相同的固定频率调度、计时和结果记录逻辑。

查询负载

该负载是刻意设计的,用来压测新数据路径的效率:查询在摄取全程持续运行,其结果必须纳入新到达的数据,而不是固定的历史切片。因此,每个系统在持续提供查询服务的同时,还必须不断为新数据做好准备。

查询标签描述的是数据路径,而非 SQL 本身是否包含聚合:聚合查询读取已维护的预聚合结果;下钻查询则直接从事件级数据行计算。

新到达的数据如何进入查询

所有六个查询都覆盖截至目前已摄取的全部历史,不设日期或时间截断:

• 按 symbol 过滤的查询(A1、A2、D1、D2): 选定的 symbol 始终不变,但随着更多行情到达,其匹配的数据会不断增长。例如 sym = 'AAPL' 既包含较早的 Apple 行情,也包含新摄取的 Apple 行情。八 symbol 自选列表也是如此。

• 不带 symbol 过滤的查询(A3、A4): 它们通过已维护的每日预聚合覆盖所有 symbol。新摄取的行情会汇入用于查询历史价格区间和每日市场活动的汇总结果。

对于聚合查询,这些新到达的行情必须纳入预聚合。对于下钻查询,新的事件级数据行必须以支持高效过滤的布局可供使用。

每个查询做什么

交互式聚合查询(A1–A4)读取持续维护的每日预聚合。A1 返回单个 symbol 的历史全量汇总;A2 汇总八 symbol 自选列表;A3 按 symbol 找出历史上最大的价格区间;A4 按天返回全市场活动。A1 和 A2 使用以 sym 开头的布局键,A3 和 A4 则读取完整的汇总。

选择性下钻查询(D1–D2)直接读取单个交易标的完整历史的事件级数据。D1 构建小时级 OHLCV K 线,包含 VWAP、波动率、价差和报价数量。D2 返回单行风险与流动性画像,涵盖中间价波动率、价差分布与尾部百分位、订单簿失衡,以及价差与深度的相关性。

预处理如何匹配查询

该工作负载会用到两种预处理方式。D1/D2 按sym过滤原始数据,sym是(sym, t)的前导列。A1/A2 按(sym, day)中同样的前导列过滤每日汇总;A3/A4 则读取所有交易标的的汇总。

每日预聚合按(sym, day)分组,并维护 A1–A4 使用的计数、求和、最小值和最大值。例如,总报价数来自对预聚合的报价计数求和,而平均价差来自用累计价差之和除以累计报价数。

缓存策略

所有系统都禁用了查询结果缓存,因此测得的运行时间反映的是查询执行本身,而不是取回先前算好的答案。这也符合该工作负载对新鲜度的要求:新到达的数据必须纳入结果,因此早先缓存的结果可能已经过时。

普通底层数据缓存则保持热态,以反映持续运行的情况。这些缓存可以降低读取数据的成本,但不能替代查询执行:引擎仍须考虑新到达的数据,并完成每个查询所需的过滤、核对或聚合。

完整的基准定义、已接受的运行记录、结果、成本摘要和复现步骤 已在 CostBench 仓库中公开。

Databricks Lakehouse/RT 仍处于 beta,因此不在这第一轮对比范围内,将在正式可用后再测试。

新数据持续到达时仍能快速作答

先看看在数据摄入与查询同时进行时,各系统的表现。下图累加了随数据集增长,回答所测聚合查询和下钻查询所花的时间。

ClickHouse Cloud 在持续摄入下累积的查询运行时长最少。

ClickHouse Cloud 从端到端专为在持续新鲜的数据上快速给出答案而构建。它的优势来自整个系统的协同工作方式——从准备每一条传入记录到返回当前答案。

快速响应这些查询只是结果的一部分。让传入数据保持可查询状态并服务该工作负载,成本是多少?CostBench 把这些维度放在一起。

CostBench 按每美元实时性能对系统排名

云平台将根本不同的计费模式,与往往截然不同的新鲜数据路径和查询引擎配对。为了比较它们的成本与性能,CostBench 将三项输入合成一个越低越好的分数:

① 新鲜数据路径成本:持续摄入、事件级布局维护和预聚合的完整摄入成本。

② 归一化查询服务成本:按各系统适用的读取侧费率执行相同计划查询的成本。

③ 总查询运行时长:主动摄入期间该查询工作负载累积的端到端运行时长。

该分数奖励那些能以经济的方式让传入数据保持可查询状态、并快速服务工作负载的系统。越低越好。

数据库存储成本不计入该分数,因为在基准测试期间其影响很小;见下方的计算说明。

分数计算与计量归一化

全路径分数的含义

该分数回答一个问题:
每花一美元,在哪里能获得最多的全路径实时性能?

它综合了让持续到达的数据保持可查询状态的成本,以及服务同一查询计划的成本和总运行时长。分数越低,意味着在持续摄入下,端到端成本更低与查询服务更快的组合越好。

计算

端到端分数 =(新鲜数据路径成本 + 归一化查询服务成本)× 总查询运行时长。越低越好。

新鲜数据路径成本

新鲜数据路径部分采用完整摄入成本,即接收全部 1132 亿行数据流,并让事件级和预聚合数据保持可查询状态。配置的计算资源按观察到的活跃时长计价;托管和无服务器服务则按其计量工作量计价。

归一化查询服务成本

我们把查询成本归一化为端到端累计运行时间 × 读侧计算价格,相当于按秒计费。这样就能比较各系统在同等付费计算时间内完成了多少查询工作。按秒归一化可以消除空闲超时和最低计费时长带来的差异。

在本次基准测试中,我们对相同数量的查询执行套用这一算法,查询在数据写入进行期间发出,并按数据集进度进行匹配。每次执行的完整端到端运行时间乘以适用的读侧计算费率,再将成本加总。得到的是归一化的对比成本,而不是对实际账单的还原。

存储成本呢?

数据库存储不计入评分。CostBench 早期用约 1132 亿行数据做的实验表明,在短时写入过程中存储的影响有限:按基准测试记录的 ClickHouse 和 Snowflake 存储费率计算,实测的原始表和预聚合占用空间对应约ClickHouse Cloud 每月 $9.83、Snowflake 每月 $16.07。

按每月 730 小时计算,若将这些完整占用空间计入整个37 小时运行,则分别增加约$0.50 和 $0.81。这里有意按最终占用空间全程计费,尽管数据集在写入过程中仍在增长。作为参照,当前对比中 fresh-data-path 的成本分别为$28.69 和 $79.42。这些存储估算只是说明量级,并非当前运行实测的存储账单。当前成本结果。

存储成本会随保留期延长而变得更加重要。这项排除针对的是数据库存储;摄取所需的基础设施,包括 Redshift 的 MSK broker 存储,仍然计入新数据路径(fresh-data-path)成本。

边界与排除项

新数据路径成本覆盖完整的 1132 亿行数据摄取。查询服务成本与总运行时间覆盖主动摄取期间匹配并通过的查询。存储、免费额度、折扣、闲置容量、最低计费、摄取完成后的查询、失败尝试以及常备兜底容量均不计入。在已通过的查询成本模型中,各服务商特有的兜底分配仍然计入。

排名

绝对得分最低的系统作为 1× 基准,其余每个系统都以 N× 差距表示。

相关方法

这将 CostBench 早先的计量粒度和排名方法从查询侧测试扩展到了完整的新数据路径。

新数据路径拉大了每美元性能的差距

我们最初的判断是:

在持续负载下,让数据保持可查询状态,对每美元性能的影响不亚于查询执行本身。

现在的结果显示出这种影响能有多大。

仅看查询侧:32–101 倍差距

早先的查询侧对比衡量的是已加载、可查询的数据,单独考察查询服务成本与运行时间。

在这一范围内,Snowflake、Redshift Serverless 和 BigQuery Capacity 的查询侧性价比比 ClickHouse差 32 到 101 倍。

加上新数据路径:412–1,996 倍差距

端到端对比加入了持续摄取新行并维持其可查询状态的成本。基准测试把这部分成本加到归一化后的查询服务成本上,再与主动摄取期间累计的查询运行时间合并。

结果就此闭环:

一旦把新鲜数据通路纳入考量,每美元性能的差距就从孤立查询侧的32–101×扩大到端到端的412–1,996×。

最后一段动画拆解了这个更大倍数背后的两个维度:端到端成本和累计查询运行时长。

最后一组对比把运行时长优势放回完整的成本语境。在这项基准测试中,ClickHouse Cloud 既拥有最低的累计查询运行时长,也拥有最低的新鲜数据通路成本和归一化查询服务成本。

• 新鲜数据通路: 后续的 1:1 分析会说明,ClickHouse Cloud 的新鲜数据通路成本最低,也是唯一一个在数据持续写入时仍能让事件级数据和预聚合数据都保持最新的受测系统。

• 查询服务: 由于这些工作在数据行到达时就已完成,其查询引擎剩下的过滤、分组和聚合工作更少,因而累计查询运行时长最短,归一化查询服务成本也最低。

ClickHouse Cloud 的优势层层叠加:成本最低的新鲜数据通路让数据一到即可查询,留下的工作量更少,测得的查询负载所需的运行时长和成本也随之更低。

CostBench 端到端实时通路系列接下来会逐一分析各家厂商的架构与计费模式,追踪查询就绪工作发生在哪里、在哪里落后,以及这些选择如何影响每美元性能。

关于我们:

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询