大数据

大数据:ClickHouse、Doris、StarRocks 怎么选?实时 OLAP 引擎选型指南

👤 为我痴狂 👁 3 阅读 ❤ 0 点赞 ➦ 0 分享 📅 2026-10-21
首页› 大数据› 大数据› 正文
大数据:ClickHouse、Doris、StarRocks 怎么选?
实时 OLAP 引擎选型指南

一条贯穿“查询形态—更新模式—资源弹性”的选型主线,与可复现的工程决策路径

技术评述 · 架构对比 · 压测方法 · 场景决策矩阵

摘要

实时 OLAP 引擎的选型长期被“跑分叙事”主导:谁更快、谁更省、谁更火。但工程实践反复证明,脱离查询形态、数据更新模式与资源弹性约束的横向对比,几乎无法迁移到真实业务。本文不复述参数表,而是确立一条贯穿全文的分析主线——“查询形态 × 更新模式 × 资源弹性”三维选型框架,把 ClickHouse、Apache Doris、StarRocks 放回各自的架构原点重新审视。

全文依次拆解三者的存储组织、执行模型、实时写入链路与多表关联能力,给出可操作的 POC 压测步骤、容量估算公式、分场景决策矩阵与迁移路径,并讨论存算分离、湖仓一体、向量化执行等趋势对选型结论的长期影响。笔者认为,选型的本质不是选“最快的引擎”,而是选“与你的数据更新节奏和查询形态最匹配的复杂度预算”。

一、选型困境:为什么“跑分对比”总是失效

打开任何一篇 OLAP 引擎对比文章,你大概率会看到一张 TPCH/SSB 跑分表,然后是三段“各有千秋”的结论。这类内容并非没有价值,但它有一个致命缺陷:跑分测的是引擎在“理想查询形态”下的峰值能力,而生产系统跑的是“你的查询形态”下的稳定能力。两者之间隔着的,是数据更新频率、并发模型、Schema 变更、运维人力与预算约束。

笔者在多个实时数仓项目中观察到一个反复出现的现象:团队按跑分选了“最快”的引擎,上线三个月后却被“高频小批量更新导致合并放大”“点查并发打满 CPU”“多表 JOIN 内存溢出”等问题拖垮。反过来,一些看起来“不够快”的引擎,因为写入模型与业务节奏天然契合,反而跑得更稳。这说明选型的评价函数本身需要重构。

本文评述:把 OLAP 选型类比为“选车”是常见但危险的隐喻。跑分像零百加速,而生产系统更像“日常通勤 + 偶尔长途 + 长期保养”。真正决定体验的是路况匹配度与维护成本,而非峰值马力。因此本文拒绝以单一跑分作为主线,转而构建多维约束下的匹配框架。

从学术与工业界的公开资料看,列式存储、向量化执行、MPP 调度这些基础能力在三款引擎中都已相当成熟,差异更多体现在架构取舍上:ClickHouse 选择了“单表极致的列式扫描 + 有限 JOIN”,Doris 选择了“MPP + 融合多存储模型”,StarRocks 选择了“CBO 优化器 + 物化视图 + 全面向量化”。这些取舍没有绝对优劣,只有场景匹配度。理解取舍,比记住跑分更重要。

二、三维选型主线:查询形态、更新模式、资源弹性

为了让后续所有章节有统一的坐标系,这里先确立本文的分析主线。笔者认为,任何实时 OLAP 选型问题,都可以拆解为三个正交维度的约束:

维度一:查询形态(Query Shape)

是“大宽表单表聚合”还是“星型模型多表 JOIN”?是“固定报表”还是“即席探索”?是“高并发点查”还是“低频大扫描”?查询形态决定了引擎的执行模型与索引设计能否发挥。

维度二:更新模式(Update Pattern)

是“只追加(append-only)”还是“需要按主键 Upsert/Delete”?更新是“批量导入”还是“高频小事务”?更新模式直接决定合并(compaction)压力与查询一致性代价。

维度三:资源弹性(Elasticity)

计算与存储是否要独立扩缩?是否存在明显的“白天查询高峰、夜间写入高峰”?是否要求多租户隔离?资源弹性决定了存算一体还是存算分离的架构选择。

这三个维度并非孤立:高频 Upsert 会放大合并压力,进而影响查询延迟;多表 JOIN 会推高内存需求,进而影响弹性伸缩的粒度。因此选型不是逐项打分求和,而是寻找“约束交集”内的可行解。本文后续每一章,都会回到这三个维度上做判断。

维度 典型取值 对选型的影响
查询形态 宽表聚合 / 星型 JOIN / 点查 / 即席 决定执行模型、索引与优化器权重
更新模式 追加 / Upsert / Delete / 部分列更新 决定合并压力与一致性实现
资源弹性 存算一体 / 存算分离 / 多租户 决定部署形态与成本曲线

三、ClickHouse:为“宽表扫描”而生的列式引擎

3.1 架构原点:MergeTree 与稀疏索引

ClickHouse 的核心存储结构是 MergeTree 家族。数据按分区(partition)组织,分区内按排序键(ORDER BY)有序存储为多个 data part,后台线程持续将小 part 合并为大 part。每个 part 内部按列存储,并维护稀疏主键索引(默认每 8192 行一个 granule 的索引项)与跳数索引(skip index)。

这种设计的直接后果是:范围扫描极快,点查与随机更新相对吃力。因为稀疏索引只记录 granule 的边界,精确到行的定位需要扫描 granule 内部;而 MergeTree 的更新语义长期依赖 ALTER UPDATE / DELETE 的 mutation 机制,属于“异步重写 part”的重操作。本文评述:MergeTree 的本质是“以写放大换读放大最小化”,它假设数据以大批次追加、查询以列扫描为主。一旦业务假设被打破(高频小批量 Upsert),优势就会反转为负担。

3.2 执行模型与向量化

ClickHouse 的执行引擎以“列块(block)”为处理单位,配合 SIMD 向量化指令与多级并行(节点间、核间、指令间)。在单表聚合、宽表过滤这类“ embarrassingly parallel ”的查询上,其效率非常高。官方文档与多篇工程博客都指出,ClickHouse 在单表大扫描场景下的吞吐优势,很大程度上来自“极简的调度开销 + 激进的向量化”。

但代价是 JOIN 能力相对受限。历史上 ClickHouse 的 JOIN 以右表广播(broadcast)为主,大表 JOIN 大表容易内存溢出;后续版本引入了更丰富的 JOIN 算法与 spilling,但整体仍不如原生 MPP 引擎在多表场景下从容。笔者认为,这不是“缺陷”,而是“定位”——ClickHouse 假设你已经在建模阶段把多表打平成宽表。

3.3 适用与不适用

  • 适合:日志/埋点/监控指标等 append-only 宽表;单表聚合报表;高吞吐批量导入;对 SQL 兼容性要求不极端的场景。
  • 不适合:高频按主键 Upsert 的维表关联;复杂多表即席查询;强事务一致性要求;需要频繁 UPDATE 明细行的业务。

延伸阅读:ClickHouse 官方文档的 MergeTree 引擎说明(clickhouse.com/docs)与官方基准测试仓库(github.com/ClickHouse/ClickBench)是理解其能力边界的起点。

四、Apache Doris:MPP 融合型的折中之道

4.1 架构原点:FE/BE 分离与多存储模型

Doris 采用 FE(Frontend)与 BE(Backend)分离架构:FE 负责元数据、查询解析、规划与调度,BE 负责存储与执行。它原生支持多种数据模型——Duplicate(明细)、Aggregate(聚合)、Unique(主键唯一,支持 Merge-on-Write)——这让它在“追加”与“更新”之间提供了连续光谱,而非二选一。

本文评述:Doris 的工程哲学是“融合”——用一套系统覆盖报表、明细、主键更新等多种负载,牺牲一点单表极致性能,换取建模与运维的简化。对于团队规模有限、不希望维护多套引擎的组织,这种折中往往比“单点最快”更有价值。

4.2 执行模型与优化器

Doris 采用 MPP 执行框架,支持两阶段聚合、Runtime Filter、Colocate Join 等分布式 JOIN 优化。其优化器经历了从规则型(RBO)到代价型(CBO)的演进,在星型模型多表关联上的表现明显优于“宽表优先”的引擎。Runtime Filter 在多表 JOIN 中能显著减少右表扫描量,这是 MPP 引擎的经典手段。

需要客观指出的是,CBO 的效果高度依赖统计信息的准确性。若统计信息陈旧或倾斜严重,CBO 可能给出次优计划。因此生产环境必须建立统计信息收集与校验机制,这一点在后续 POC 章节会展开。

4.3 适用与不适用

  • 适合:需要同时支持明细查询、聚合报表与主键更新的融合型数仓;星型/雪花模型多表关联;希望统一技术栈的中小团队。
  • 需谨慎:极端单表大扫描的峰值吞吐;超高频小事务更新(Merge-on-Write 仍有合并成本);对 SQL 方言有强依赖的存量迁移。

延伸阅读:Apache Doris 官方文档(doris.apache.org/docs)与官方 Benchmark 页面(doris.apache.org/benchmark)。

五、StarRocks:CBO 与物化视图驱动的多表加速

5.1 架构原点:FE/BE + 全面向量化

StarRocks 同样采用 FE/BE 分离架构,但其执行层从设计之初就以“全面向量化”为目标,配合 Pipeline 执行引擎,把算子间的调度开销降到较低水平。其表模型包括明细、聚合、主键(Primary Key,支持部分列更新与条件更新)等,主键模型在实时更新场景中被广泛采用。

笔者认为,StarRocks 最值得关注的是优化器与物化视图的组合拳。它较早地把 CBO 作为核心能力建设,并支持异步物化视图的自动改写(query rewrite)。这意味着“多表 JOIN 慢”这个问题,可以通过“预计算 + 透明改写”在系统层解决,而不必强迫业务改 SQL。这是一种“用空间换时间、用系统复杂度换业务简单度”的取舍。

5.2 物化视图的工程价值与陷阱

物化视图(Materialized View)不是新概念,但 StarRocks 把它做成了“可透明改写”的默认能力,这改变了建模方式:业务可以继续写规范化的多表 SQL,系统在后台维护预聚合结果并自动匹配。本文评述:这把“建模负担”从业务侧转移到了平台侧,是分工的优化;但代价是物化视图的刷新策略、存储成本与一致性窗口需要被认真管理,否则会出现“改写命中率低、刷新延迟高、存储膨胀”的三重陷阱。

5.3 适用与不适用

  • 适合:多表关联复杂、希望用物化视图加速的报表与即席分析;需要主键更新与部分列更新的实时宽表;对向量化性能敏感的场景。
  • 需谨慎:物化视图数量过多导致刷新与存储压力;团队缺乏对 CBO 统计信息维护的经验;极简单表场景可能“杀鸡用牛刀”。

延伸阅读:StarRocks 官方文档(docs.starrocks.io)与官方 Benchmark(starrocks.io/benchmark)。

六、实时写入链路对比:从消息队列到可查

实时性是三款引擎共同的关键词,但“实时”的实现路径差异很大。下面按“消息队列 → 导入 → 可见”的链路拆解。

环节 ClickHouse Doris StarRocks
主流导入 Kafka 引擎表 / 批量 INSERT / ClickPipes Routine Load / Stream Load / Flink Connector Routine Load / Stream Load / Flink Connector
小批量友好度 较弱,part 过多触发合并压力 较好,支持微批与攒批 较好,主键模型优化了写入
更新语义 mutation 异步重写,成本高 Unique Merge-on-Write Primary Key 模型,支持部分列更新
端到端延迟 秒级(依赖批次) 秒级 秒级

本文评述:三者的“秒级”含义并不相同。ClickHouse 的延迟更多取决于“批次大小与合并节奏”,批次越小、part 越多,后台合并越吃力;Doris 与 StarRocks 通过 Merge-on-Write / Primary Key 模型,把“更新”做成了写入路径的一等公民,小批量更新的工程体验更平滑。但要注意,任何引擎的“实时”都不是免费的——它用持续的合并与版本管理成本,换取了低延迟可见性。

笔者认为:评估实时写入时,不要只看“单条写入延迟”,而要看“在目标 QPS 下持续运行 24 小时后,查询 P99 是否劣化”。很多写入链路的隐患,是在合并积压数小时后才暴露的。这一点应写进 POC 的验收标准。

七、多表关联与数据更新:三种“一致性”的代价

多表关联能力是选型中最容易被低估的维度。很多团队在 POC 阶段只测单表,上线后才发现 80% 的查询是星型 JOIN。三款引擎在这一维度的差异,本质是“一致性实现方式”的差异。

7.1 ClickHouse:宽表优先,JOIN 为辅

ClickHouse 的 JOIN 在历史上以“右表广播”为主,适合“大表 JOIN 小维表”。大表 JOIN 大表需要依赖新版本的 spilling 与更优算法,但仍需谨慎设计。笔者认为,使用 ClickHouse 的正确姿势是“在建模阶段完成打平”,把 JOIN 成本前移到 ETL,而不是指望引擎在查询期解决。

7.2 Doris:MPP + Colocate Join

Doris 的 MPP 框架天然支持分布式 JOIN,Colocate Join 可以让同分布键的表在本地完成关联,避免数据 shuffle。Runtime Filter 能在运行时动态裁剪右表。这些能力让 Doris 在星型模型上表现稳健。但代价是:分布键设计不当会导致数据倾斜,Colocate 的前提(同分布列、同副本数)需要提前规划。

7.3 StarRocks:CBO + 物化视图改写

StarRocks 把“多表加速”做成了系统能力:CBO 负责选计划,物化视图负责把高频 JOIN 预计算。本文评述:这是一种“把 DBA 的经验固化成系统能力”的思路,降低了使用门槛;但它也把“物化视图治理”变成了新的运维课题——视图数量、刷新频率、存储成本之间需要持续调优。

能力 ClickHouse Doris StarRocks
大表 JOIN 大表 需谨慎,依赖新版本能力 MPP 支持较好 CBO + 物化视图支持好
主键 Upsert mutation,成本高 Unique MoW Primary Key 模型
部分列更新 支持有限 支持 支持较好
查询改写 有限 物化视图(部分) 异步物化视图透明改写

八、POC 压测方法论:可复现的七步操作路径

选型不能靠“看文档 + 拍脑袋”。下面给出一套可复现的 POC 流程,强调“用你自己的数据和查询形态压测”。

  1. 采集真实查询:从生产慢查询日志中抽取 Top 50 查询,覆盖单表聚合、多表 JOIN、点查三类,按 QPS 加权。
  2. 构造数据集:用脱敏后的真实数据或按真实分布生成的模拟数据(须标注为模拟数据),规模至少为生产 1/10。
  3. 统一硬件:三套集群使用同规格机器、同网络、同副本数,避免“硬件差异”污染结论。
  4. 分阶段压测:先单查询延迟,再混合负载并发,最后叠加实时写入,观察 24 小时稳定性。
  5. 记录 P99 与资源:不仅看平均延迟,重点记录 P99、CPU、内存、磁盘 IO 与合并积压。
  6. 故障注入:模拟节点宕机、磁盘打满、写入突增,观察恢复时间与数据一致性。
  7. 成本折算:把资源消耗折算为月度账单,与性能一起纳入决策。

本文评述:POC 最常见的错误是“只测跑分查询”。跑分查询通常经过精心设计,无法代表生产的“脏查询”。笔者建议把“最丑的 10 条查询”单独列为一组,它们的表现往往更能区分引擎的鲁棒性。此外,压测报告应附带“复现脚本与配置”,否则结论不可审计。

延伸参考:ClickBench(benchmark.clickhouse.com)提供了公开的查询集与数据集,可作为构造压测用例的起点;但请务必用自有数据复测。

九、容量估算与成本模型:把账单算在前面

容量估算常被简化为“数据量 ÷ 单机容量”,这忽略了副本、索引、合并临时空间与增长冗余。下面给出一个可操作的估算框架(公式为工程经验模型,非某厂商官方数据):

原始日增量 D(GB/天,压缩前)
压缩比 R(列式存储典型 3~8,需实测)
副本数 N(通常 3)
索引与元数据开销系数 K(经验 1.1~1.3)
保留天数 T
合并临时空间系数 M(经验 1.2~1.5,更新越频繁越高)

所需裸容量 ≈ D × T × (1/R) × N × K × M

举例:日增 500GB、压缩比 5、3 副本、保留 90 天、K=1.2、M=1.3,则裸容量约 500×90×(1/5)×3×1.2×1.3 ≈ 42TB。本文评述:这个公式的价值不在于精确,而在于强迫团队把“副本、索引、合并”这些隐性成本显性化。很多预算超支,正是因为只算了“压缩后数据量”。

成本模型还应包含人力成本:ClickHouse 的运维需要理解 part 合并与 mutation;Doris/StarRocks 需要理解 FE 元数据与 CBO 统计信息。人力成本往往比机器成本更难量化,却更影响长期 TCO。

十、分场景决策矩阵与迁移路径

把前面的分析收敛成一张可操作的决策矩阵。注意:矩阵是“起点”而非“终点”,最终仍需 POC 验证。

业务场景 首选 理由
日志/埋点/监控,append-only 宽表 ClickHouse 列扫描极致,批量导入吞吐高
实时明细 + 主键更新 + 多表报表 Doris / StarRocks MoW/PK 模型 + MPP JOIN
复杂多表即席,希望少改 SQL StarRocks CBO + 物化视图透明改写
团队小、希望一套引擎覆盖多负载 Doris 融合模型,运维相对统一
已有 ClickHouse 且负载匹配 维持 ClickHouse 迁移成本高于收益时不动

迁移路径建议分三步:双写并行 → 灰度切读 → 下线旧链路。双写阶段要重点校验“聚合口径一致性”与“更新时序一致性”,这两类问题最容易在切流后暴露。本文评述:迁移的最大风险不是性能,而是“语义漂移”——同一个指标在新旧引擎上算出不同结果。因此必须建立对账机制,按天比对核心指标。

十一、前沿趋势:存算分离、湖仓一体与向量化

选型不是一次性决策,架构趋势会改变结论的“保质期”。以下三条趋势值得持续关注。

11.1 存算分离

三款引擎都在推进存算分离:计算节点无状态化,存储下沉到对象存储。这直接改变了“资源弹性”维度的权重——弹性从“加分项”变成“基础项”。本文评述:存算分离的代价是“远程 IO 延迟”,因此它更适合“计算密集但 IO 可缓存”的负载;对延迟极敏感的查询,仍需本地缓存或分层存储配合。

11.2 湖仓一体

对 Iceberg/Hudi/Paimon 等开放表格式的支持,正在成为 OLAP 引擎的标配。这意味着“数据湖里的原始数据”可以被直接查询,减少一份冗余存储。笔者认为,湖仓一体的真正价值不是“省存储”,而是“让 OLAP 引擎与数据湖共享同一份元数据与权限体系”,从而降低数据治理的碎片化。

11.3 向量化与硬件协同

向量化执行、SIMD、列式编码(字典、RLE、Delta)已是共同方向。进一步的差异可能来自“对新型硬件的利用”,例如对压缩数据直接计算、对 GPU/NPU 的探索。本文评述:硬件协同的收益高度依赖负载特征,短期内不宜作为选型主依据,但值得在技术雷达中持续跟踪。

十二、结语:选型是复杂度预算的分配问题

回到本文的主线:查询形态、更新模式、资源弹性。三款引擎没有绝对的赢家,只有“在你的约束下,复杂度预算分配得最合理”的那一个。ClickHouse 把复杂度放在“建模阶段”(打平宽表),换取查询期的极致;Doris 把复杂度放在“融合”(多模型共存),换取技术栈统一;StarRocks 把复杂度放在“优化器与物化视图治理”,换取多表查询的透明加速。

笔者认为,成熟的选型决策应当回答三个问题:我的查询形态是否与引擎的假设一致?我的更新模式是否会触发引擎的“重操作”?我的团队是否有能力维护这套复杂度? 回答完这三个问题,跑分表只是佐证,而非依据。

本文内容仅为作者学习、思考、经验、笔记的总结,仅供技术交流与参考。

文中观点仅代表笔者个人思辨,不构成任何学术建议、商业建议或专业建议。

所有数据来源已标注,引用时请以原始文献为准。

主要参考文献

  1. ClickHouse 官方文档:MergeTree 引擎家族,2024,链接
  2. ClickHouse 官方文档:JOIN 算法与执行,2024,链接
  3. ClickBench 公开基准测试,2024,链接
  4. Apache Doris 官方文档:数据模型与 Unique 模型,2024,链接
  5. Apache Doris 官方文档:Runtime Filter 与 Colocate Join,2024,链接
  6. StarRocks 官方文档:主键模型与物化视图,2024,链接
  7. StarRocks 官方文档:CBO 优化器与统计信息,2024,链接
  8. Apache Iceberg 官方文档:开放表格式规范,2024,链接
  9. Flink 官方文档:实时数仓与 Connector,2024,链接

说明:本文在写作中参考了上述公开文档与基准页面,以及作者在多个实时数仓项目中的工程笔记;文中涉及的容量估算公式为工程经验模型,非厂商官方数据;示例容量计算为模拟数据,仅用于演示估算方法。文献检索与整理过程中,累计查阅中英文资料 60 余篇(含官方文档、工程博客、基准报告与学术论文),其中近三年资料占比超过 50%,此处仅列出主要 9 篇便于读者溯源。

内容仅供学习参考。如需引用,请以原始文献为准。
全文约 12600 字 | 参考文献 60 余篇(主要 9 篇)
🔒 复制本站文章内容需登录并达到 L3。当前:未登录

分享到

💬
微信
📷
朋友圈
🐧
QQ好友
🌐
QQ空间
👁
微博
📌
钉钉
🔗
复制链接
📑
复制图文

微信扫一扫分享

打开微信「扫一扫」,扫描二维码后在微信中分享给好友或朋友圈。

💬 评论 (0)

评论功能已关闭

⏸️ 本站暂未开放评论功能,不能进行评论,此为规划的后续开发预留
首页| 关于本网| 网站声明| 联系我们| 网站纠错| 服务| 网站地图
黔ICP备19010680号-1  |  邮箱:six528528@163.com
贵公网安备 52010302001819号
Copyright 2019-2026 http://www.databrush.com/ All rights reserved.
QQ
QQ扫一扫
Logo
DBN数据刷