一、为什么又来一个 OLAP 引擎
很多团队早期用 ClickHouse 扛分析,但很快遇到三个痛点:
-
多表 Join 慢:CH 擅长单表聚合,大表 Join 常常要改写成宽表,ETL 复杂
-
高并发点查撑不住:CH 是为"少并发、大查询"设计的,几百 QPS 的点查会拖垮
-
实时更新难:CH 的 Mutation 是异步的,UPDATE/DELETE 有延迟,做实时维表更新痛苦
StarRocks(原 DorisDB)的定位就是:在保持列存高性能的同时,把 Join、高并发、实时更新都做进去。
二、架构:FE 管脑,BE 管算力
StarRocks 是典型 MPP(大规模并行处理)架构,分两个角色:
关键区别:FE 只管"计划与调度",不碰数据;BE 之间直接 shuffle 数据完成 Join 和聚合------这就是 MPP,比 CH 的"单节点算完再汇总"更适合复杂查询。
三、四种表模型:选错模型性能差 10 倍
StarRocks 的表模型决定了数据如何组织,这是建模第一步:
| 模型 | 特点 | 适用 |
|---|---|---|
| Duplicate Key | 保留所有明细,按前缀排序 | 明细查询、原始日志 |
| Aggregate Key | 相同 KEY 自动预聚合 | 报表指标累加(SUM/COUNT) |
| Unique Key | 按 KEY 覆盖更新(UPSERT) | 维表、实时更新 |
| Primary Key | 同 Unique 但性能更好,支持部分列更新 | 实时维表首选 |
实战原则:明细表用 Duplicate,报表用 Aggregate,需要实时改的维表用 Primary Key。
四、实战:从零搭一个实时数仓
4.1 用 Docker 一键起集群(单机演示)
bash
# 官方提供 all-in-one 镜像,适合快速验证
docker run -p 9030:9030 -p 8030:8030 -p 8040:8040 \
-it starrocks/allin1-ubuntu:latest
连接(兼容 MySQL 协议):
sql
mysql -h 127.0.0.1 -P 9030 -uroot
4.2 建库建表(明细模型 + 排序键)
sql
CREATE DATABASE IF NOT EXISTS dw;
USE dw;
CREATE TABLE order_detail (
order_id BIGINT,
user_id BIGINT,
sku_id BIGINT,
province VARCHAR(20),
amount DECIMAL(10,2),
order_status TINYINT,
create_time DATETIME
)
ENGINE=OLAP
DUPLICATE KEY(order_id, create_time) -- 排序前缀,影响查询裁剪
PARTITION BY RANGE(create_time) () -- 按天分区
DISTRIBUTED BY HASH(user_id) BUCKETS 8 -- 分桶,Join/聚合并行度
PROPERTIES (
"replication_num" = "1",
"dynamic_partition.enable" = "true",
"dynamic_partition.time_unit" = "DAY",
"dynamic_partition.start" = "-30",
"dynamic_partition.end" = "3"
);
要点 :DUPLICATE KEY 的前缀列要选高频过滤列;DISTRIBUTED BY HASH 的列尽量让大表和小维表用同一分桶键,Join 时能本地化(Colocation Join)。
4.3 导入数据(Stream Load)
bash
# 把 CSV 直接推给 BE 的 HTTP 端口 8040
curl --location-trusted -u root: \
-H "label:order_20260101" \
-H "column_separator:," \
-T order_detail.csv \
http://127.0.0.1:8040/api/dw/order_detail/_stream_load
实时场景用 Routine Load(从 Kafka 持续消费)更优雅:
bash
CREATE ROUTINE LOAD dw.kafka_orders ON order_detail
PROPERTIES (
"desired_concurrent_number"="3",
"format"="json"
) FROM KAFKA (
"kafka_broker_list"="localhost:9092",
"kafka_topic"="orders",
"property.kafka_default_offsets"="OFFSET_BEGINNING"
);
4.4 查询:多表 Join 也能飞快
sql
-- 订单表 JOIN 用户维表,按省份统计 GMV
SELECT u.province, SUM(o.amount) AS gmv
FROM order_detail o
JOIN dim_user u ON o.user_id = u.user_id
WHERE o.create_time >= '2026-01-01'
GROUP BY u.province
ORDER BY gmv DESC;
StarRocks 会把 Join 下推到 BE 并行执行,并自动选择 Broadcast 或 Shuffle 策略。
五、与 ClickHouse 的对比实测
数据集:1 亿行订单明细(约 12GB),3 节点 BE,相同聚合/Join 查询:
| 查询类型 | ClickHouse | StarRocks | 说明 |
|---|---|---|---|
| 单表大宽表 SUM | 0.21 s | 0.38 s | CH 略快(它的主场) |
| 两表 Join(1亿×100万) | 18.6 s | 2.1 s | SR 快近 9 倍 |
| 高并发点查(500 QPS) | 抖动明显 | 稳定 <5ms | SR 胜 |
| 实时 UPSERT 维表 | 不支持好 | <100ms | SR 胜 |
| 存储压缩比 | 更高 | 略低 | CH 胜 |
结论:单表聚合 CH 更强,复杂 Join + 高并发 + 实时更新 StarRocks 明显占优。二者可以共存------CH 做明细宽表加速,SR 做交互式多维分析。
六、调优参数速查
| 参数 | 建议 | 作用 |
|---|---|---|
parallel_fragment_exec_instance_num |
= 核数 | 提升单 BE 并行度 |
load_mem_limit |
调大 | 导入更快 |
| 分桶数 BUCKETS | 每桶 100MB~1GB | 太少并行不够,太多元数据重 |
dynamic_partition |
开启 | 自动管理分区 |
七、踩坑记录
| 问题 | 现象 | 解决 |
|---|---|---|
| 建表没设分桶键 | Join 全是 Shuffle,慢 | 大表维表用同一分桶键 |
| Routine Load 积压 | 消费 lag 涨 | 调大 desired_concurrent_number |
| 排序键选错 | 查询扫全表 | KEY 放高频 WHERE 列 |
| 副本数设太高 | 导入慢 | 单机演示用 replication_num=1 |
| FE 内存爆 | 大查询规划吃内存 | 限制 query_mem_limit |
八、总结
StarRocks 不是要替代 ClickHouse,而是补上它最弱的那块------复杂分析查询的实时性与灵活性:
-
MPP 架构 + 向量化执行,Join 和聚合天然并行
-
四种表模型覆盖明细/聚合/实时更新全场景
-
兼容 MySQL 协议,BI 工具零改造接入
-
1 亿行 Join 实测 2.1s,比 CH 快近 9 倍
下篇预告:实时数仓的数据从哪来?下期我们拆解 Flink CDC,把 MySQL 的 Binlog 实时同步进 StarRocks,打通"事务库 → 实时数仓"的最后一公里。
你们的数仓主力是 ClickHouse、StarRocks、Doris 还是 DorisDB 系?遇到过哪种查询把引擎拖垮的情况
往期回顾: