资讯动态

实时数仓选型:Flink+StarRocks vs ClickHouse vs Doris 深度对比与决策树

发布时间:2026/10/16 9:01:28 来源:尧图企业网站定制
一、先定义清楚你要解决什么实时数仓是个被用滥的词。选型之前必须先分清你要支撑的是哪一种负载因为这三种形态的最优解完全不同形态 A追加型日志分析Append-only特征数据只增不改典型如用户行为日志、IoT 遥测、埋点事件。查询多为时间范围 维度下钻 聚合。典型查询 SELECT dt, channel, COUNT(DISTINCT user_id), SUM(amount) FROM user_event_log WHERE dt BETWEEN 2026-09-01 AND 2026-09-23 AND event_type purchase GROUP BY dt, channel;核心诉求单表扫描快、压缩比高、写入吞吐大。 →ClickHouse 的主场。形态 B可变状态宽表Mutable / UPSERT特征数据会更新典型如订单状态待付款→已付款→已发货、用户画像标签、库存余额。需要按主键做 UPSERT且查询要求读到最新状态。典型查询订单状态实时看板 SELECT status, COUNT(*), SUM(amount) FROM order_wide WHERE create_time 2026-09-23 GROUP BY status; -- 要求 status 是最新状态不是历史快照核心诉求主键更新UPSERT、去重、多表 Join 打宽。 →StarRocks / Doris 的主场。形态 C高并发点查Serving特征QPS 数千到数万查询条件是主键或索引返回单条或少量记录。典型如用户详情页实时指标风控特征查询。典型查询 SELECT * FROM user_profile_agg WHERE user_id 10086; -- QPS 峰值 8000要求 p99 20ms核心诉求点查延迟、并发能力、缓存。 → 三者都能做但都不是最优解真要极致点查该上 HBase/Redis 宽表不过在顺便支撑层面 StarRocks 的行存 索引更合适。重要提醒很多团队选型的失败源于用形态 A 的引擎去扛形态 B 的负载最常见用 ClickHouse 存订单状态表然后被 UPSERT 折磨到崩溃。先分类再选型。二、选型维度定义别只比跑分我见过太多ClickHouse vs Doris 谁快的对比最后发现赢的那个在真实业务里跑不起来。原因是维度定义错了。生产选型至少要评估这 8 项维度为什么重要权重建议1. 写入吞吐与实时性能不能吃下 Flink 的写入峰值★★★★★2. 单表查询性能形态 A 的核心★★★★★3. 多表 Join 能力形态 B 的核心也是分水岭★★★★★4. 数据更新UPSERT状态类数据的刚需★★★★☆5. 高并发点查形态 C★★★☆☆6. 运维复杂度决定你能不能养得起★★★★☆7. 生态集成Flink/Kafka/Hive/Iceberg 对接★★★★☆8. 成本机器 人力★★★★☆三、三引擎架构对比┌──────────────────────────────────────────────────────────────┐ │ ClickHouse列存 MergeTree 向量化 │ │ ┌────────┐ ┌────────┐ ┌────────┐ │ │ │ Shard1 │ │ Shard2 │ │ Shard3 │ ← 依赖 ZK/Keeper 管副本 │ │ │(Repl) │ │(Repl) │ │(Repl) │ │ │ └────────┘ └────────┘ └────────┘ │ │ 特点稀疏索引 数据分区内有序单表扫描极快 │ │ 软肋分布式 Join 能力弱需改写/预聚合UPSERT 靠 │ │ ReplacingMergeTree 异步合并读到最新要加 FINAL │ ├──────────────────────────────────────────────────────────────┤ │ StarRocksBE FE 架构全面向量化 CBO 优化器 │ │ ┌─────────────┐ │ │ │ FE (元数据/CBO)│ ← 支持复杂查询计划、Join 重排序 │ │ └──────┬──────┘ │ │ ┌─────┴─────┬─────────┬─────────┐ │ │ │ BE1 │ BE2 │ BE3 │ ← 列存 主键表支持 │ │ └───────────┴─────────┴─────────┘ 实时 UPSERT │ │ 特点CBO 优化器强多表 Join / 大表关联表现好 │ │ Primary Key 表原生支持 UPSERT查询即最新 │ ├──────────────────────────────────────────────────────────────┤ │ DorisFE BE 架构与 StarRocks 同源后分道 │ │ ┌─────────────┐ │ │ │ FE (MySQL协议)│ ← 兼容 MySQL 协议上手最顺 │ │ └──────┬──────┘ │ │ ┌─────┴─────┬─────────┬─────────┐ │ │ │ BE1 │ BE2 │ BE3 │ ← Unique/Aggregate 模型 │ │ └───────────┴─────────┴─────────┘ │ │ 特点三种数据模型Duplicate/Unique/Aggregate │ │ MySQL 协议亲和生态集成Flink CDC成熟 │ └──────────────────────────────────────────────────────────────┘三者的血缘关系值得一提StarRocks 和 Doris 同源都源自 Apache Doris 早期版本所以架构理念、数据模型、甚至很多 SQL 语法都相近。差异主要在StarRocks 在向量化执行器和 CBO 优化器上做了更彻底的重构查询性能特别是 Join 上更强Doris 则在社区生态和 MySQL 协议兼容性上持续投入。四、场景化压测四类基准实测以下数据来自我们内部的基准环境3 台 32C128G NVMe各自部署默认配置用于横向对比量级不代表官方最优。数据集SSB 1000 万行 自建订单状态表 2000 万行。基准 1单表明细聚合形态 ASELECT dt, channel, COUNT(*), SUM(amount) FROM event_log WHERE dt 2026-09-01 AND dt 2026-09-23 GROUP BY dt, channel ORDER BY dt;引擎耗时相对说明ClickHouse0.42 s1.0×列存 向量化单表扫描最强StarRocks0.68 s1.6×接近略逊Doris0.81 s1.9×同量级结论单表扫描 ClickHouse 领先但三者在同一量级都在 1 秒内这点差距通常不构成选型依据。基准 2多表 Join形态 B 的分水岭-- 事实表 2000万 维表150万 维表210万 SELECT c.region, p.category, SUM(o.amount) FROM orders o JOIN customers c ON o.cust_id c.id JOIN products p ON o.prod_id p.id WHERE o.dt 2026-09-01 GROUP BY c.region, p.category;引擎耗时相对说明StarRocks1.24 s1.0×CBO 自动选 Colocate/Bucket Shuffle JoinDoris1.87 s1.5×优化器持续改进同量级ClickHouse4.6 s3.7×需手动改写为 IN/字典原生分布式 Join 弱这是真正的分水岭。ClickHouse 的分布式 Join 是出了名的坑大表 Join 容易 OOM通常需要把维表做成Dictionary内存字典或者改写为子查询 IN或者在 Flink 侧就打宽预 Join 成大宽表。前两种方案在小维表上可行一旦维表变大或需要多跳 Join维护成本急剧上升。基准 3UPSERT 实时更新形态 B 的刚需场景Flink CDC 实时同步订单表状态字段持续更新要求查询即最新。引擎实现方式更新吞吐查询一致性坑StarRocksPrimary Key 表~8 万行/s强一致查询即最新主键表内存占用高DorisUnique KeyMoW~6 万行/s强一致Merge-on-Write 有写放大ClickHouseReplacingMergeTree~15 万行/s最终一致需FINAL或argMax异步合并ClickHouse 的写入吞吐反而最高但它给的是最终一致新写入的数据在未合并前查询可能返回旧版本或重复行。要读到最新必须加FINAL性能损失明显或用argMax聚合改写。而 StarRocks/Doris 的主键/唯一键模型查询天然就是最新的。这一项往往是一票否决项。如果你的业务有订单状态实时看板库存实时余额用 ClickHouse 会非常痛苦。基准 4高并发点查形态 C单主键查询SELECT * FROM user_agg WHERE user_id ?逐步加压引擎QPSp99 50msp99 延迟说明StarRocks~1200018 ms行存 主键索引点查优化到位Doris~900026 ms支持行存/点查优化ClickHouse~550041 ms列存点查需读多列非其强项注意这三者在形态 C 上都不是专业选手。如果 QPS 要到数万且延迟要求个位数毫秒正确做法是HBase/Redis OLAP分层或至少加一层缓存。别硬扛。五、逐个剖析与场景推荐StarRocks极速统一多表关联与湖仓一体首选优势CBO 优化器强多表 Join / 复杂查询表现最好Primary Key 表原生 UPSERT实时更新强一致湖仓一体查 Iceberg/Hive/Hudi 外表能力成熟一份数据多处分析支持物化视图自动改写对 BI 场景友好。代价主键表Primary Key内存占用较高主键索引常驻内存数据量大时内存成本高生态相对年轻某些周边工具不如 ClickHouse 丰富运维需要对 FE/BE 有理解扩容缩容有门槛。适合需要多表 Join 的实时报表 / Ad-hoc 分析订单状态、用户画像等需要 UPSERT的场景想做湖仓一体、减少数据搬运的团队已经有 Flink 做实时打宽、需要下游强一致查询的链路。ClickHouse单表之王成本与极限性能首选优势单表扫描与压缩比一骑绝尘压缩后体积常为原始 1/5~1/10省存储写入吞吐极高批量写入百万行/秒级生态极其丰富Grafana 集成、各种表引擎、周边工具运维简单单机就能发挥很强性能小规模团队友好。代价分布式 Join 弱最大软肋UPSERT 是最终一致状态类数据要绕并发能力一般默认配置下单机并发不宜过高需要调优集群规模大时ZK/Keeper 和副本管理会变复杂。适合追加型日志 / 埋点 / 时序数据分析它的绝对主场单表为主的宽表查询在 Flink 侧打宽后写入对存储成本敏感、数据量极大的场景压缩比是硬优势团队规模小、希望运维简单的场景。Doris生态亲和上手最快优势MySQL 协议兼容任何 MySQL 客户端/BI 工具直连学习成本最低三种数据模型Duplicate/Unique/Aggregate覆盖常见需求生态集成成熟Flink-Doris-Connector、Spark-Doris、CDC 整库同步社区活跃中文资料丰富。代价极限性能特别是复杂 Join略逊 StarRocks部分高级特性如极强的 CBO迭代中与 StarRocks 功能重叠选型时容易纠结。适合团队已有 MySQL 技术栈、希望平滑迁移需要快速上线、不愿投入大量学习成本以固定报表为主的场景需要整库同步CDC能力成熟的场景。六、决策树可以直接照抄补充混合部署是常态不是妥协现实中最常见的架构其实是分层混合Flink 实时链路 │ ├── 【ClickHouse】存原始明细日志形态 A │ └─ 支撑明细查询、日志检索、用户行为分析 │ └── 【StarRocks】存打宽后的状态宽表形态 B └─ 支撑实时看板、多维报表、UPSERT 场景 │ └─ 【Redis】缓存热点指标形态 C理由很简单让每个引擎做自己最擅长的事。ClickHouse 存海量明细省存储、写入快StarRocks 存需要 Join 和更新的宽表Redis 扛点查。维护两套引擎的额外成本远小于用一个引擎硬扛所有形态带来的痛苦。我们的实践日志类数据日均 80 亿条走 ClickHouse订单/用户状态2000 万行走 StarRocks热点聚合结果缓存到 Redis。整体机器成本比全用 StarRocks低约 35%比全用 ClickHouse少了无数 UPSERT 的绕路。6.4 迁移路径从 ClickHouse 迁到 StarRocks 怎么做到不停机很多团队是先用 ClickHouse 起步后来被 Join 和 UPSERT 逼着迁移。直接停机切换不现实我们用的是双写 灰度切读四步法第一步双写2 周。Flink Sink 同时写 ClickHouse 和 StarRocks两边都写全量。这一步的风险是写入压力翻倍需要先评估 Flink 作业的资源余量通常 CPU 加 30% 够用。第二步数据一致性比对1 周。写个比对任务每天抽样比对两边的核心指标-- 两边各跑一次比对结果差异 SELECT dt, COUNT(*) AS cnt, SUM(amount) AS amt FROM order_wide WHERE dt 2026-09-23 GROUP BY dt;差异率降到 0.01% 以下再进入下一步。这一步千万别跳我们第一次迁移时跳过比对结果 StarRocks 侧有个时区配置问题导致跨天数据错位上线后才被发现。第三步灰度切读2 周。按业务模块逐步把查询切到 StarRocks先切内部看板出问题影响小再切核心报表最后切对外 API。每个阶段观察 2~3 天重点看查询耗时和错误率。第四步下线 ClickHouse 写链路。确认所有读流量都切走后停掉 ClickHouse 的 Sink保留 ClickHouse 集群只读一段时间作为回滚备份一个月后彻底下线。整个周期大约 5~6 周其中第二步的比对是最容易被压缩但最不该压缩的环节。另外提醒三步走期间两套引擎并存机器成本会翻倍要提前跟老板说清楚这是临时状态。6.5 容量规划集群到底要几台机器选型定了马上要回答一个很现实的问题集群规模怎么估给一套能直接套的公式避免拍脑袋订机器上线后要么不够用要么浪费。ClickHouse 侧单节点32C128G NVMe单表扫描可支撑约 5~10 亿行明细的亚秒查询写入吞吐百万行/秒级。节点数按原始数据总量 ÷ 单节点可用存储 × 副本数 × 1.3膨胀系数估算。它的压缩比通常能到 5~10 倍所以原始 10 TB 的日志落到磁盘大约 1.5 TB三副本加膨胀系数约 6 TB两台 NVMe 节点就能吃下。StarRocks 侧主键表因为内存常驻索引内存是硬约束。单 BE 节点建议把主键表内存控制在物理内存的 40% 以内128G 内存留 50G 给索引超了就分表或改用 Duplicate Key。节点数按并发查询峰值 × 单查询平均内存 ÷ 单节点可用内存 × 冗余系数估算务必预留 30% headroom 应对突增。一个反直觉的提醒很多团队按当前数据量估忽略了增速。日志类数据常见半年翻倍建集群时直接按 18 个月后的量预留比半年后扩缩容迁移省心得多——而 OLAP 的扩缩容往往意味着数据重分布比加机器本身麻烦得多。七、7 个必踩的坑坑 1ClickHouse 的分布式 Join 直接 OOM。大表 Join 大表ClickHouse 默认可能把右表全量拉到内存。务必维表用Dictionary小维表大表关联改写成IN子查询或用GLOBAL JOIN注意GLOBAL语义最根本的在 Flink 侧预打宽别让 ClickHouse 干这活。坑 2ClickHouse 的 ReplacingMergeTree 读到旧数据。不加FINAL就可能读到重复/旧版本。生产上要么统一加FINAL接受性能损失要么用argMax聚合改写-- 替代 FINAL 的常见写法 SELECT id, argMax(status, version), argMax(amount, version) FROM order_table GROUP BY id;坑 3StarRocks 主键表内存暴涨。Primary Key 表的主键索引常驻内存行数过亿或主键过长时内存压力很大。对策主键尽量短、评估内存容量、必要时改用 Duplicate Key 外部去重。坑 4Flink 写入的小批次问题。无论哪个引擎Flink Sink 如果每来一条就写一次会把引擎写垮尤其 ClickHouse 讨厌小批量。必须配置攒批// Flink - ClickHouse/StarRocks Sink 攒批配置要点 .withBatchSize(10000) // 攒够 1 万行再写 .withBatchIntervalMs(5000) // 或 5 秒超时触发 .withMaxRetries(3)同时注意攒批会引入延迟实时性要求和写入效率之间要权衡这就是所谓的mini-batch取舍。坑 5分区与分桶设计一开始就定错。分桶数bucket/分 shard一旦建表就很难改。原则ClickHouse 按dt分区单分区数据量控制在百万~千万行级StarRocks/Doris 分桶数 ≈ 总行数 / 单桶目标行数建议单桶 1~10 GB且要考虑后续扩容分桶数最好是 BE 节点数的整数倍。坑 6并发一上来就雪崩。ClickHouse 默认max_concurrent_queries不高高并发下会排队。需要调优连接池 服务端并发参数且业务侧做好限流。StarRocks/Doris 稍好但同样需要压测确定并发上限。坑 7拿 OLAP 当 OLTP 用。最常见也最致命。实时数仓是分析引擎不是事务库。不要在上面做单条记录高频更新 强事务的事。如果你的需求是每次用户操作就更新一条并立刻读那是 HBase/Cassandra/MySQL 的活OLAP 扛不住。八、结论先分形态再选型这一步比什么都重要。日志类的形态 A 给 ClickHouse状态宽表的形态 B 给 StarRocks 或 Doris形态 C 的点查加一层缓存。选错形态比选错引擎严重得多后者只是慢一点前者是天天绕路。真正的分水岭是 Join 和 UPSERT。单表扫描三者差距不到 2 倍这点差距不构成决策依据多表 Join 差 3.7 倍UPSERT 的一致性是质的差别这两项才是选型时该反复掂量的。混合部署是成熟团队的常态不是妥协。日志走 ClickHouse、宽表走 StarRocks、热点走 Redis整体成本和体验都优于一套引擎打天下。运维复杂度也要算进成本ClickHouse 单机友好StarRocks 需要理解 FE/BEDoris 最平滑你的团队能不能养得起比跑分重要。还有一句可能反直觉的话Flink 侧的攒批和预打宽影响比引擎选型更大。很多所谓的引擎性能问题根子是写入姿势不对小批次写入能把任何 OLAP 引擎写垮。迁移的话留够时间别压缩比对环节。双写加一致性比对加灰度切读5~6 周是合理周期。省下的那一周通常会用一次线上事故还回去。先用真实数据跑一遍你的核心查询再决定。本文的压测是通用基准你的数据分布、查询模式、并发特征才是最终裁判。花两天做一次真实 POC比吵一周的架有用得多。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑