
一、Tablet/Replica 架构
1.1 数据层级结构
StarRocks 数据组织层级:Table → Partition → Bucket (Tablet) → Replica → Rowset → Segment
- Table: 逻辑表,由一个或多个 Partition 组成
- Partition: 按分区键划分的数据子集,支持表达式分区(v3.0+,推荐)、Range分区(Legacy)、List分区(Legacy)
- Bucket (Tablet): 分区内按分桶策略划分的最小数据分片,也是数据复制、迁移、均衡的最小单位
- Replica: Tablet 的副本,默认 3 副本,确保数据可靠性
- Rowset: 一次数据导入生成的数据版本文件集合,一个 Tablet 包含多个 Rowset
- Segment: Rowset 内的数据段文件,列式存储的基本单位
1.2 分桶策略
| 策略 | 说明 | 适用场景 |
|---|---|---|
| Random Bucketing (v3.1+默认) | 随机分桶,无需指定 HASH 键 | 通用场景,简化建表 |
| Hash Bucketing | 按 HASH 键分桶,相同键值路由到同一桶 | 需要局部数据聚合的 Join/Agg |
| Range + Hash | Range分区 + Hash分桶 | 时序+维度场景 |
| List + Hash | List分区 + Hash分桶 | 枚举值+维度场景 |
1.3 副本管理
- 默认 3 副本(
replication_num = 3) - Shared-nothing 模式: 副本存储在 BE 本地磁盘
- Shared-data 模式: 数据存储在对象存储/HDFS,本地仅缓存
- 副本是数据复制、迁移、均衡的最小单位
- FE 负责副本调度和均衡策略
1.4 设计取含
| 决策 | 原因 |
|---|---|
| Tablet 作为最小调度单位 | 细粒度均衡,避免大表迁移开销 |
| 默认 3 副本 | 平衡数据可靠性与存储成本 |
| Hash 分桶 | 相同键值本地聚合,减少网络 Shuffle |
| Random 分桶(v3.1+) | 简化建表,自动均匀分布 |
关键参数 : PARTITION BY, DISTRIBUTED BY HASH, BUCKETS, replication_num
参考: https://docs.starrocks.io/docs/table_design/data_distribution
二、Segment 存储格式(列式页面、Zone Map、索引)
2.1 Segment 文件结构
一个 Segment 文件是列式存储的基本单元,包含以下部分:
Segment 文件
├── Data Region(数据区)
│ └── 每列的 Data Pages(默认 64KB / page)
├── Index Region(索引区)
│ ├── Ordinal Index(行号 → Data Page 物理地址映射)
│ ├── Zone Map Index(每列每个 Data Chunk 的 Min/Max/HasNull/HasNotNull)
│ ├── Bitmap Index(可选,按列存储)
│ ├── Bloom Filter Index(可选,按列存储)
│ └── Prefix Index(排序键前缀索引)
├── Footer
│ ├── 各列索引的偏移量
│ ├── Segment 元信息
│ └── Footer 长度 & 魔数
2.2 列式 Data Page
- Data Page 大小 : 默认 64KB(
data_page_size = 64 * 1024) - 每列数据独立存储在各自的 Data Pages 中(纯列存)
- v3.2+ 支持行列混合存储 (
"storage_format" = "native"),行列混合 Page 适用于点查询场景 - Data Page 内数据按排序键有序排列
- 数据经压缩后存储(LZ4/ZSTD/zlib/Snappy)
2.3 Ordinal Index(序号索引)
- 内置自动索引,无需手动创建
- 每个 Data Page 生成一条 Ordinal Index 条目,记录起始行号
- 功能:通过行号定位列 Data Page 的物理地址
- 实现从逻辑行号到物理 Page 偏移的映射
2.4 Data Chunk
- 数据按排序键排序后,每 1024 行组成一个逻辑数据块(Data Chunk)
- Zone Map 按 Data Chunk 维度存储统计信息
- Prefix Index 按 Data Chunk 维度构建索引条目
2.5 设计取含
| 决策 | 原因 |
|---|---|
| 64KB Data Page | 平衡 IO 效率与内存使用,适配列式压缩 |
| 每 1024 行一个 Chunk | Zone Map 和 Prefix Index 的最小粒度,过滤效率与索引大小平衡 |
| 列式存储 | 高压缩比、按列读取、向量化执行友好 |
| 行列混合(v3.2+) | 点查询场景减少 IO 放大 |
参考: https://docs.starrocks.io/docs/table_design/indexes / https://docs.starrocks.io/docs/table_design/data_compression
三、数据写入过程(MemTable → Flush → Compaction)
3.1 写入全流程
数据写入请求
↓
1. FE 接收 Load 请求,生成 LoadJob,分配事务 ID
↓
2. BE 接收数据,写入 MemTable(内存中的排序树)
↓
3. MemTable 满(达到阈值),Flush 到磁盘生成 Rowset(一个版本的数据文件集合)
↓
4. Rowset 包含多个 Segment 文件(列式存储)
↓
5. 事务 Publish,数据可见
↓
6. 后台 Compaction 合并多个 Rowset
3.2 MemTable 阶段
- 数据写入 BE 时,首先进入内存中的 MemTable
- MemTable 是一个排序树结构(SkippableList),数据按排序键有序插入
- 在写入过程中,相同键的数据按表模型进行合并:
- Duplicate Key: 不合并,全部保留
- Aggregate Key: 按聚合函数合并(SUM/MAX/MIN/REPLACE等)
- Unique Key: 追加写入,不做在线合并
- Primary Key: 加载主键索引,DELETE标记DelVector,UPDATE执行Delete+Insert
- MemTable 达到阈值后触发 Flush
3.3 Flush 阶段
- MemTable 数据按排序键已有序,直接 Flush 生成 Segment 文件
- 每个 Segment 文件包含:
- 列式 Data Pages(压缩后)
- Ordinal Index
- Zone Map Index
- Prefix Index(基于排序键)
- Bitmap Index / Bloom Filter Index(如有)
- 多个 Segment 文件组成一个 Rowset(对应一次导入的数据版本)
3.4 数据版本管理
- 每次导入生成一个新 Rowset,分配递增版本号
- Tablet 中的数据 = Base Rowset + 多个 Cumulative Rowset + 多个增量 Rowset
- 查询时需要合并多个 Rowset 的数据
- 版本数越多,查询性能越差(尤其是 Merge-on-Read 的 Unique Key 表)
3.5 设计取含
| 决策 | 原因 |
|---|---|
| MemTable 排序写入 | 保证 Segment 内数据按排序键有序,利于 ZoneMap 过滤和前缀索引 |
| 批量 Flush | 减少 Segment 文件数,避免小文件问题 |
| 版本化 Rowset | 支持并发读写,数据一致性通过 MVCC 保证 |
| Primary Key 的 Delete+Insert | 写入时即标记删除,查询无需在线合并,3-10x 性能提升 |
参考: https://docs.starrocks.io/docs/table_design/table_types/primary_key_table
四、Compaction 策略(Cumulative + Base)
4.1 Compaction 概述
每次数据导入生成一个新 Rowset(数据版本文件),长期积累会产生大量小文件,降低查询效率。Compaction 负责合并多个 Rowset 为更大的文件。
4.2 Shared-nothing 模式 Compaction
Cumulative Compaction(增量合并):
- 合并最近多个小 Rowset 为一个较大的 Cumulative Rowset
- 不包含 Base Rowset
- 触发条件:增量 Rowset 数量达到阈值
cumulative_compaction_num_deltas_per_compaction(默认 5) - 聚合模型在此阶段会进一步合并相同聚合键的数据
Base Compaction(基线合并):
- 将 Cumulative Rowset 与 Base Rowset 合并为新的 Base Rowset
- 聚合模型彻底合并;Merge-on-Read 模型(Unique Key)彻底合并多版本
- 触发条件:Cumulative Rowset 数量达到阈值
base_compaction_num_cumulative_deltas(默认 5) - Base Compaction 开销较大,触发频率低于 Cumulative Compaction
Compaction 层级示意:
增量 Rowset → [Cumulative Compaction] → Cumulative Rowset → [Base Compaction] → Base Rowset
(最新小文件) (较大中间文件) (最大基线文件)
4.3 Shared-data 模式 Compaction
Shared-data 模式采用FE 控制的 Compaction 机制:
- Score 计算: Leader FE 根据事务 Publish 结果计算并存储每个分区的 Compaction Score
- 候选选择: FE 选择 Max Compaction Score 最高的分区作为合并候选
- 任务生成: FE 发起 Compaction 事务,生成 Tablet 级子任务,分发到 CN 节点
- 子任务执行 : CN 后台执行,并发数由
compact_threads控制 - 结果收集: FE 聚合子任务结果并提交 Compaction 事务
- Publish: FE 发布成功提交的 Compaction 事务
Compaction Score 规则:
- 每个 Data File 贡献 1 分
- Tablet 的 Rowset 按 Size 分组,文件数最多的组决定该 Tablet 的 Score
- MaxCS < 10: Compaction 完成
- MaxCS > 100: 不健康状态
- MaxCS > 500: 非常高,可能需要手动干预
4.4 关键参数
| 参数 | 默认值 | 说明 |
|---|---|---|
cumulative_compaction_num_deltas_per_compaction |
5 | 触发 Cumulative Compaction 的增量 Rowset 数 |
base_compaction_num_cumulative_deltas |
5 | 触发 Base Compaction 的 Cumulative Rowset 数 |
compact_threads |
- | CN 上并发 Compaction 线程数 |
lake_compaction_score_selector_min_score |
10 | FE 参数,Score 低于此值视为完成 |
lake_ingest_slowdown_threshold |
100 | FE 参数,Score 超过此值减速导入 |
lake_compaction_score_upper_bound |
2000 | FE 参数,Score 超过此值拒绝导入 |
4.5 设计取含
| 决策 | 原因 |
|---|---|
| 两级 Compaction | Cumulative 轻量级频繁执行,Base 重度低频执行,平衡性能与开销 |
| Shared-data FE 控制 | 数据在共享存储,FE 全局调度更高效 |
| Score 驱动的流控 | 防止 Compaction 延迟过高导致查询性能严重退化 |
| 限制导入速率 | 避免小文件堆积超过系统处理能力 |
参考: https://docs.starrocks.io/docs/administration/management/compaction
五、索引类型
5.1 Prefix Index(前缀索引)
原理: 数据按排序键排序后,每 1024 行组成一个逻辑数据块,取每块第一行排序键列值构建索引条目。查询过滤条件匹配前缀索引时,可快速定位数据块。
关键限制:
- 索引条目不能超过 36 字节
- 只对排序键的前缀列有效(最左前缀匹配)
- 一张表只有一个前缀索引
设计取含:
- 36 字节限制平衡索引大小与查询效率
- 最左前缀匹配规则,建议将高频过滤列放在排序键前面
- v3.0+ Primary Key 和 v3.3+ 所有模型支持 ORDER BY 独立定义排序键,增加前缀索引灵活性
参考: https://docs.starrocks.io/docs/table_design/indexes
5.2 Zone Map Index
原理: 自动内置索引,存储每个 Data Chunk 的统计信息:Min、Max、HasNull、HasNotNull。查询时根据统计信息快速判断 Data Chunk 是否可跳过。
特性:
- 内置自动索引,无需手动创建
- 对排序列效果最佳(数据有序,Min/Max 区间紧凑)
- 对非排序列效果有限(Min/Max 区间分散)
- 仅支持范围过滤(>、<、=、BETWEEN 等)
设计取含: 自动创建、零维护成本;排序键列天然高效,非排序列效果有限是可接受的折衷
5.3 Bitmap Index
原理: 使用位数组(Bit Array),每个 bit 对应表中一行。查询时根据位图快速定位行号,支持 AND/OR 位运算。
适用场景:
- 高基数列的等值查询(如 ID 列)
- 多个低基数列组合查询(AND/OR)
- 过滤效果需至少过滤 999/1000 数据行
自适应选择机制:
- 阈值:
bitmap_max_filter_ratio / 1000(默认 1) - 查询条件值数 / 列基数 < 阈值时使用 Bitmap Index
- 否则自动跳过,避免加载索引开销超过收益
支持操作 : =, IN, >, >=, <, <=, IS NULL;不支持 !=, NOT LIKE
创建范围:
- Duplicate/Primary Key 表:所有列
- Aggregate/Unique Key 表:仅 Key 列
关键参数 : bitmap_max_filter_ratio(BE 配置,默认 1,范围 1-1000)
设计取含:
- 不同于传统认知(Bitmap 适合低基数),StarRocks Bitmap 更适合高基数等值查询
- 自适应选择避免误用,1000:1 过滤比是经验阈值
- 加载 Bitmap 有 IO 开销,不适合低选择性查询
参考: https://docs.starrocks.io/docs/table_design/indexes/bitmap_index
5.4 Bloom Filter Index
原理 : 空间高效的概率数据结构,判断数据一定不存在 或可能存在。查询时若 Bloom Filter 判断数据文件不含目标值,直接跳过该文件。
特性:
- 适合高基数列(如 ID 列)的 = 和 IN 查询
- 有假阳性(误判存在),无假阴性(一定不存在)
- 仅支持 = 和 IN 操作
- 可通过 ALTER TABLE 动态增删
创建范围:
- Duplicate/Primary Key 表:所有列
- Aggregate/Unique Key 表:仅 Key 列
支持数据类型: SMALLINT, INT, BIGINT, LARGEINT, CHAR, STRING, VARCHAR, DATE, DATETIME
关键参数 : bloom_filter_columns(表属性,指定列名)
验证方法 : 查询 Profile 中 BloomFilterFilterRows 字段
设计取含:
- Bloom Filter 空间效率极高,但仅支持等值查询
- 假阳性可接受(最多少跳过一些文件,不漏数据)
- 与 Prefix Index 互补:Prefix 处理排序键,Bloom Filter 处理非排序高基数列
参考: https://docs.starrocks.io/docs/table_design/indexes/bloomfilter_index
5.5 N-gram Bloom Filter Index(v3.3+, Beta)
原理 : 特殊的 Bloom Filter 索引,将字符串按 N-gram 分片后构建 Bloom Filter。加速 LIKE 查询和 ngram_search 函数。
适用场景:
- LIKE 模糊查询加速
ngram_search/ngram_search_case_insensitive函数加速
仅支持字符串类型: STRING, CHAR, VARCHAR
参考: https://docs.starrocks.io/docs/table_design/indexes/ngram_bloom_filter_index
5.6 Full-text Inverted Index(全文倒排索引)
原理: 倒排索引,快速定位包含关键词的数据行,加速全文搜索。
5.7 Vector Index(向量索引)
原理: 支持近似最近邻搜索(ANNS),用于向量检索场景。
5.8 Z-order Index
注意 : StarRocks 官方文档中未提供 Z-order Index 作为标准索引类型。Z-order 排序主要出现在部分技术博客和社区讨论中,作为多维数据排序优化的一种思路(将多维数据映射到一维以改善多维查询的局部性),但并非 StarRocks 内置索引。StarRocks 通过 Prefix Index + Bitmap Index + Bloom Filter 的组合来处理多维查询场景。
5.9 索引对比总结
| 索引类型 | 自动/手动 | 适用查询 | 适用列 | 过滤方式 |
|---|---|---|---|---|
| Prefix Index | 自动 | 前缀等值/范围 | 排序键前缀 | 快速定位 Data Chunk |
| Zone Map | 自动 | 范围过滤 | 所有列(排序列最佳) | Min/Max 跳过 Chunk |
| Ordinal Index | 自动 | 行号定位 | 所有列 | 行号→物理地址 |
| Bitmap Index | 手动 | 高基数等值/IN/多列组合 | PK/Duplicate全列,其他Key列 | 位图定位行号 |
| Bloom Filter | 手动 | 高基数等值/IN | 同上 | 排除不含值的 Page |
| N-gram BF | 手动 | LIKE/ngram_search | 字符串列 | 排除不含子串的 Page |
| Full-text | 手动 | 全文搜索 | 字符串列 | 倒排索引 |
| Vector | 手动 | ANN 搜索 | 向量列 | 近似最近邻 |
参考: https://docs.starrocks.io/docs/table_design/indexes
六、数据压缩
6.1 压缩算法对比
| 算法 | 压缩比 | 解压速度 | 推荐场景 |
|---|---|---|---|
| LZ4(默认) | 中 | 最快 | 通用场景,性能优先 |
| ZSTD | 较高 | 较快 | 平衡存储与性能 |
| zlib | 最高 | 最慢 | 存储空间优先 |
| Snappy | 最低 | 快 | 不推荐 |
6.2 设计取含
- 压缩比排名:zlib > ZSTD > LZ4 > Snappy
- 推荐 LZ4 或 ZSTD:两者在压缩比和解压性能间有良好平衡
- 压缩算法仅建表时指定,不可修改
- 压缩不仅节省存储空间,还减少 IO 开销(I/O 密集任务受益)
- 代价:额外的 CPU 消耗(压缩/解压)
关键参数 : compression(表属性,建表时指定,默认 LZ4)
参考: https://docs.starrocks.io/docs/table_design/data_compression
七、磁盘数据布局
7.1 Shared-nothing 模式(BE 本地存储)
{storage_root_path}/
├── data/
│ └── {shard_id}/
│ └── {tablet_id}/
│ ├── {schema_hash}/
│ │ ├── {rowset_id}_0.dat # Segment 数据文件
│ │ ├── {rowset_id}_0.idx # Segment 索引文件
│ │ ├── {rowset_id}_1.dat
│ │ ├── {rowset_id}_1.idx
│ │ └── ...
│ └── tablet_meta # Tablet 元信息
└── ...
- 每个 Tablet 目录下存储多个 Rowset
- 每个 Rowset 由 .dat(数据)和 .idx(索引)文件对组成
- Primary Key 表额外存储:主键索引文件、DelVector 文件
- BE 支持多存储路径(SSD + HDD 混合部署)
7.2 Shared-data 模式(对象存储/HDFS)
s3://bucket/
├── {partition_id}/
│ └── {tablet_id}/
│ ├── {rowset_id}_0.dat
│ ├── {rowset_id}_0.idx
│ └── ...
└── ...
- 数据存储在对象存储(S3/Azure Blob/GCS/OSS)或 HDFS
- CN 节点本地缓存热点数据(Data Cache)
- 持久化索引可存本地磁盘(v3.1.4)或对象存储(v3.3.2,
persistent_index_type = CLOUD_NATIVE)
7.3 Segment 文件内部布局
Segment File (.dat)
┌─────────────────────────────────┐
│ Column 1 Data Pages (compressed) │
│ Column 2 Data Pages (compressed) │
│ ... │
│ Column N Data Pages (compressed) │
├─────────────────────────────────┤
│ Ordinal Index (per column) │
│ Zone Map Index (per column) │
│ Bitmap Index (optional, per col) │
│ Bloom Filter Index (optional) │
│ Prefix Index │
├─────────────────────────────────┤
│ Footer │
│ ├── Column index offsets │
│ ├── Segment metadata │
│ └── Footer length + magic │
└─────────────────────────────────┘
7.4 设计取含
| 决策 | 原因 |
|---|---|
| 列式 Data Page 64KB | 适配压缩算法工作块大小,平衡 IO 与内存 |
| 数据与索引同文件 | 减少文件数,顺序 IO 读取 |
| Shared-data 分离存储 | 弹性扩缩容,存储计算分离降低成本 |
| 本地 Data Cache | 缓解对象存储延迟,保持查询性能 |
八、参考链接
- 数据分布(Tablet/Replica/分区/分桶): https://docs.starrocks.io/docs/table_design/data_distribution
- 表达式分区: https://docs.starrocks.io/docs/table_design/data_distribution/expression_partitioning
- 索引概览: https://docs.starrocks.io/docs/table_design/indexes
- Bitmap 索引: https://docs.starrocks.io/docs/table_design/indexes/bitmap_index
- Bloom Filter 索引: https://docs.starrocks.io/docs/table_design/indexes/bloomfilter_index
- 数据压缩: https://docs.starrocks.io/docs/table_design/data_compression
- Compaction 管理: https://docs.starrocks.io/docs/administration/management/compaction
- Primary Key 表: https://docs.starrocks.io/docs/table_design/table_types/primary_key_table
- 架构概览: https://docs.starrocks.io/docs/introduction/Architecture
- GitHub 源码: https://github.com/StarRocks/starrocks