
简介EMR StarRocks 白皮书是一份面向大数据工程师、数仓架构师及数据分析决策者的企业级 MPP 数据仓库技术文档系统阐述 StarRocks 的架构设计与核心理念。内容涵盖 FE、BE 两类进程的协作机制、全面向量化引擎、CBO 优化器、现代化物化视图以及实时数仓、用户画像、实时风控、订单分析等真实场景与携程、顺丰、京东等行业落地案例帮助读者快速理解产品选型与技术落地路径。资源为单个 PDF 文件压缩包大小约 13.78MB便于下载后随时查阅。已有 242 人学习该资料适合正在评估极速统一数据分析方案、或需要系统了解 StarRocks 核心优势与适用场景的从业者参考。1. 极速全场景 MPP为什么这份 EMRStarRocks 白皮书值得先读再动手EMRStarRocks 白皮书是一份把 StarRocks 这个极速全场景 MPP 数据仓库讲透的技术资料核心观点非常直接用 FE、BE 两类进程把实时分析、离线分析、数据湖分析统一到同一套引擎上让企业不用再维护“烟囱式”的数仓架构。适合正在做 OLAP 选型、被 MySQL 大查询压得难受、或者想把 Kafka 数据做到秒级可见的数仓工程师。读完这份文档你能搞清 StarRocks 的架构边界、三种数据模型的选型逻辑、六条数据导入链路的适用条件以及部署运维里那些不试不知道的坑。它不是产品广告更像一份从原理到落地的工程笔记值得在下单集群之前先花半天读完。2. 架构与数据模型FE/BE 职责划分和三种建表模型的选型逻辑2.1 FE 与 BE两类进程如何撑起无单点集群白皮书里对架构的描述很简洁整个 StarRocks 集群的核心只有 FrontendFE和 BackendBE两类进程不依赖 HDFS、ZooKeeper 这类外部组件。这一点在生产环境里价值极大部署复杂度低出故障时排查面也小。FE 负责元数据管理、客户端连接、查询规划和查询调度。FE 内部通过类 Paxos 的 BDBJE 协议选主注意这里的约束集群中必须有半数以上 Follower 存活才能完成选主。元数据写入必须得到多数 Follower 确认Observer 节点不参与选主只异步同步并回放日志主要用来扩展查询并发。每个 FE 都在内存保留一份完整元数据所以任何一个 FE 都能提供无差别服务前端接入层不需要再做一层路由。BE 是后端节点负责数据存储和 SQL 计算执行。BE 完全对等导入时数据直接写入 BE不经 FE 中转执行查询时FE 先把 SQL 转成逻辑执行单元再按数据分布拆成物理执行单元分发到数据所在的 BE 节点执行避免数据跨节点拷贝。这就是 StarRocks 多表关联快的一个重要原因能本地算的绝不搬数据。部署形态上我一般建议 3 FE 起步其中 2 个 Follower、1 个 ObserverBE 至少 3 台。FE 不要只部署一个否则元数据选主机制形同虚设节点一挂整个集群的元数据写入就停了。BE 的数量则要看数据量和查询并发白皮书里说单集群可扩展到数百节点、数据规模到 10PB 级别实际项目里从 3 台 BE 起步的占绝大多数。2.2 明细、聚合、主键三种数据模型选错代价很大StarRocks 的建模灵活性和 MySQL 很不一样。MySQL 建表就是一张表但 StarRocks 要根据业务语义在明细模型Duplicate Key、聚合模型Aggregate Key、主键模型Primary Key里选一个这是建表时就要做的决定后续改模型要重建表。明细模型存的是原始明细数据插入一行就存一行适合需要召回全部历史明细、数据不频繁更新的场景。常见的订单流水、日志明细都适合用 Duplicate Key。它的缺点是更新代价高不适合按主键频繁修改。聚合模型会在数据导入时按主键和指定聚合函数合并数据。同一个主键重复导入时指标列按 SUM、MAX、MIN 这类函数累加或覆盖。适合订单汇总、流量统计这类只需要结果值的场景。代价是你查不到历史明细只能查到累积结果。白皮书里特别提醒使用聚合模型时导入的顺序会影响聚合结果如果业务对数据可见性要求高要谨慎。主键模型是为了频繁更新场景设计的支持 UPSERT 语义主键不存在就插入存在就更新。它用 Insert and Delete 模式实现比 Merge on Read 策略的实时导入性能和查询性能都好。用户画像、订单状态更新、库存变化这类场景直接选 Primary Key 模型。三种模型的对比我整理成了下面这张表方便你在评审表结构时直接对照。模型存储语义更新能力典型场景代价Duplicate Key每行独立存储不支持主键更新日志明细、流水存储占用大Aggregate Key按主键预聚合按聚合函数合并指标汇总、报表查不到明细Primary Key按主键 upsert支持高频更新画像、订单状态实时合并有开销2.3 Range 分区 Hash 分桶Tablet 才是数据管理的真正单元StarRocks 支持两级数据分布第一级是 Range 分区第二级是 Hash 分桶。简单理解Range 分区把表按区间拆成多个子表通常按时间分Hash 分桶在分区内再按分桶键的哈希值把数据切开每个哈希区间形成一个子表Tablet。Tablet 是多副本冗余、数据均衡、故障恢复的最小单位。Range 分区主要解决两个问题一是大量删除数据的性能按时间分区后删除一个分区比逐行 DELETE 快得多二是生命周期管理StarRocks 支持动态创建新分区和自动删除过期分区这就是 TTL 能力不用再写定时任务去清理数据。Hash 分桶键的选择直接影响查询剪裁效果。分桶键哈希值相同的数据落在同一个 Tablet如果查询条件里带分桶键系统就能直接定位到少量 Tablet大幅减少扫描量。我习惯选高基数的查询筛选项做分桶键比如 order_id、user_id用 city_code 这种低基数列做分桶键很容易出现数据倾斜某些 Tablet 数据量特别大查询和导入都会慢。白皮书提到每个 Tablet 的副本由单独的本地存储引擎管理导入和查询最终都落到 Tablet 副本上。也就是说分桶数不是随便定的它决定了并发度和均衡粒度。一般建议每个 BE 上 Tablet 数量控制在几百到几千之间太多会导致元数据膨胀太少则并发扩展受限。3. 数据接入的六条路径从 Stream Load 到 Spark Load 怎么选3.1 导入方式对照先看数据量再看同步方式StarRocks 的导入不是只有一种六种路径对应不同数据源和数据量级。如果选错轻则导入效率低重则任务超时。白皮书给了很清晰的分类逻辑看数据量、看数据源、看同步还是异步。导入方式数据源数据量同步方式适用场景Stream Load本地文件/C SV/JSON10GB 以下同步程序写入、小批量文件Broker LoadHDFS/S3 等10GB-1000GB异步外部存储大文件Spark LoadHive/HDFSTB 级异步首次迁移、全量导入Routine LoadKafka持续流入异步实时数据接入Insert IntoStarRocks 内部百 MB 级同步轻量转换、程序写入Flink ConnectorFlink 作业流批均可异步ETL 后写入这里有个容易混淆的点Stream Load 虽然是同步方式但它的内部实现是 FE 收到 HTTP 请求后把任务重定向给某个 BE 作为 Coordinator由 Coordinator 调度多个 BE 并行写入最终结果同步返回给客户端。所以 10GB 以下的文件走 Stream Load 是合理的再大就建议换 Broker Load避免单次 HTTP 连接长时间占用。3.2 Stream Load 实战用 curl 完成一次带 label 的导入Stream Load 是最常用的导入方式因为它不需要额外部署组件一条 curl 命令就能完成。下面是一次真实作业里常见的写法。curl --location-trusted -u root: \ -H label: load_order_20250115_001 \ -H column_separator:, \ -H columns: order_id,user_id,amount,pay_time \ -T /data/order/order_20250115.csv \ http://127.0.0.1:8030/api/demo/orders/_stream_load这段命令的意图是把 order_20250115.csv 文件导入 demo 库的 orders 表列分隔符是逗号源文件列顺序和表结构列名通过 columns 参数映射。label 是这次导入作业的唯一标识它的作用非常重要同一个 label 重复执行时StarRocks 会直接复用第一次的结果不会重复写入数据。这就像给导入任务上了一个“后悔药”机制程序重试时不用担心数据翻倍。参数说明8030 是 FE 的 HTTP 端口实际请求会被重定向到 BE所以端口也可能变成 BE 的 be_http_portcolumns 里如果源文件和表结构完全一致可以省略如果源文件第一行是表头需要加 -H skip_header:1。3.3 Routine Load 与 FlinkKafka 流式写入的两种路径实时场景里Routine Load 是消费 Kafka 数据进 StarRocks 的主力。它不需要额外部署 Flink 集群直接在 StarRocks 里建一个常驻任务就行。CREATE ROUTINE LOAD demo.kafka_order_load ON orders COLUMNS(order_id, user_id, amount, pay_time) PROPERTIES ( format csv, desired_concurrent_number 3, max_batch_interval 20 ) FROM KAFKA ( kafka_broker_list 10.0.0.11:9092,10.0.0.12:9092, kafka_topic order_topic, kafka_partitions 0,1,2, property.kafka_default_offsets OFFSET_BEGINNING );这个任务创建之后FE 会把 Routine Load 拆成若干子任务每个子任务消费指定的一部分分区数据导入结束后 FE 会自动生成新的子任务继续消费失败的任务会重试。desired_concurrent_number 控制消费者的并发度一般和 Kafka 分区数对齐如果分区数是 3并发设 3 就够了设太大反而增加调度开销。如果已经用了 Flink 做实时计算更推荐 flink-connector-starrocks。这个插件会把数据先缓存再批量转换成 Stream Load 模式写入支持 exactly once 语义。实现原理是Flink 做 checkpoint 时保存一批数据和对应的 labelcheckpoint 完成后下一次写入之前阻塞刷新这批数据StarRocks 端用 label 机制保证同一批数据只写一次。外部系统保证 At Least OnceStarRocks 的 label 保证 At Most Once合起来就是 Exactly Once。4. 部署与使用避坑五条能让集群“翻车”的典型问题4.1 问题一主键模型当明细模型用导致存储与更新双双恶化现象用户画像表按天全量导入数据量不大但 BE 磁盘占用持续上涨导入耗时越来越长。原因建表时用了 Duplicate Key 模型。相同主键的数据不会覆盖每次全量导入都追加一份新数据旧数据还占着磁盘查询时还会扫到多版本数据。解决确认业务是“按主键更新”还是“只追加明细”。用户画像、订单状态、库存这类场景建表时必须用 Primary Key 模型。如果已经建成 Duplicate Key只能新建表用 INSERT INTO SELECT 或 Stream Load 把数据迁过去没有在线改模型的后路。4.2 问题二Stream Load 偶发 timeoutCoordinator 节点和超时参数没调对现象10GB 左右的文件导入时有时候成功有时候失败报 timeout重试又能过。原因Stream Load 是通过 FE 重定向到某个 BE 执行这个 BE 同时承担 Coordinator 和写入任务。大文件导入时Coordinator 要等所有 BE 写完才能返回结果默认超时时间在数据量大、磁盘慢的情况下不够用。解决导入前估算数据量超过 10GB 直接上 Broker Load不要硬扛。小文件超时则检查 be.conf 里的 stream_load_timeout_second一般 300 秒起步根据文件大小和集群性能调整同时确认 Coordinator 节点的磁盘吞吐写入慢的 BE 是超时主因。4.3 问题三Routine Load 消费位点重置数据重复或丢失现象Routine Load 任务报错重启后Kafka 消费位点回到最早导致大量数据重复导入聚合模型下 SUM 指标翻倍。原因Routine Load 的 offset 管理依赖 StarRocks 内部的消费进度记录。如果任务频繁失败或者创建任务时 property.kafka_default_offsets 设成了 OFFSET_BEGINNING每次任务重建都会从最早位置重新消费。解决创建 Routine Load 时明确指定 offset 策略通常是 OFFSET_END 或从最近位点开始任务异常时先看 SHOW ROUTINE LOAD 的日志和进度不要盲目重启。如果已经确认重复导入Primary Key 模型可以靠主键覆盖Aggregate 模型只能重建任务并清掉受影响分区的数据再重新导入。4.4 问题四多表关联性能忽高忽低Join 策略没被 CBO 选对现象同一个关联查询表数据量没大变但上午跑 2 秒下午跑 30 秒。原因StarRocks 的 CBO 优化器依赖统计信息选择 Join 方式。如果没有执行 ANALYZE TABLE 收集统计信息CBO 对表行数、数据分布的判断会偏差很大可能把 Broadcast Join 选成 Shuffle Join网络开销飙升。解决建表后和关键数据导入后都执行 ANALYZE TABLE更新统计信息。再看执行计划里 Join 的类型小表关联大表时应该走 Broadcast Join 或 Colocate Join如果走了 Shuffle Join检查两张表的 join key 和分桶键是否一致一致时可以用 Bucket Shuffle Join 省掉数据分发。4.5 问题五资源组配置后查询反而变慢分类器匹配超出预期现象给核心业务配置了高优先级资源组结果 Adhoc 查询也被分到这个组大查询把 CPU 打满核心业务响应变慢。原因资源组是通过分类器匹配的分类器里的 USER、ROLE、SOURCE_IP、QUERY_TYPE 条件如果写得太宽比如只按 USER 匹配所有该用户的查询都被归入同一资源组大小查询互相抢资源。解决分类器尽量组合多个条件比如 USER 加 QUERY_TYPE或者 SOURCE_IP 加 ROLE上线前用 SHOW RESOURCE GROUPS 查看实际匹配情况确认大查询被分到了独立组。资源组的 CPU_CORE_LIMIT 和 MEM_LIMIT 要按 BE 节点总资源比例计算别拍脑袋写数值否则容易出现配置了限制但没生效的假象。5. 用 EXPLAIN 验证一切先看执行计划再谈优化很多人排查慢查询第一件事是看 SQL 写法我建议反过来先看 EXPLAIN 的执行计划。StarRocks 的 CBO 已经把谓词下推、分区分桶裁剪、Join 顺序这些事包了SQL 写得太“聪明”反而可能干扰优化器。拿到一条慢查询直接执行下面的命令先确认数据扫描范围对不对。EXPLAIN SELECT u.user_name, SUM(o.amount) FROM orders o JOIN users u ON o.user_id u.id WHERE o.pay_time 2025-01-01 AND o.pay_time 2025-02-01 GROUP BY u.user_name;看执行计划时重点盯三个位置关注点看什么异常信号分区裁剪partitions 字段显示扫描全部分区分桶裁剪tablet 数量扫描 Tablet 数远大于命中数Join 方式join 算子类型小表关联走了 Shuffle Join谓词下推过滤条件下推到 scan 节点过滤留在 join 之后才执行按时间范围过滤却没触发分区裁剪大概率是分区字段没建对或者查询里对分区列做了函数运算导致剪裁失效。Join 方式异常时先 ANALYZE TABLE 再重试大部分情况下统计信息更新后 CBO 会自动纠正。慢查询调优完成后我习惯把优化前后的 EXPLAIN 计划存到同一个对比文档里记录表数据量、分区数、Join 类型三个关键参数。这个习惯救过我很多次——集群扩容或数据量增长后之前的优化方案可能失效翻出当时的 EXPLAIN 对比一眼就能看出是统计信息过期还是分区策略变了。从那以后我每次排查慢查询都强制走一遍 EXPLAIN 再动 SQL少走了不少弯路。希望这份笔记能帮你在 StarRocks 上少踩几个坑把白皮书的原理真正落到自己的集群里。本文还有配套的精品资源点击获取