
一、数据模型概览
StarRocks 提供四种表类型:Duplicate Key(明细模型)、Aggregate(聚合模型)、Unique Key(唯一键模型)和 Primary Key(主键模型)。建表时必须指定表类型并定义排序键,数据导入时按排序键排序后存储。
核心共性
- 排序键(Sort Key):数据导入时按排序键排序存储,查询时可通过排序键快速过滤
- 前缀索引(Prefix Index):基于排序键自动生成,限制 36 字节
- 自 v3.0 起 Primary Key 表支持 ORDER BY 独立定义排序键;自 v3.3 起所有表模型均支持
- 建表后不可修改表类型
参考:https://docs.starrocks.io/docs/table_design/table_types/
二、Duplicate Key 表(明细模型)
2.1 原理与机制
- StarRocks 默认表模型,未指定时自动创建
- 追加写入(Append-Only),不支持修改历史数据
- 相同主键的记录全部保留,不做合并,源数据与存储行一一对应
- 可定义排序键,查询包含排序键列时加速过滤
2.2 排序机制
- 建表时通过
DUPLICATE KEY或ORDER BY定义排序键 - 数据导入时按排序键排序后存储
- 自 v3.3.0 起,支持使用
ORDER BY指定排序键,可以是任意列的组合 - 如果同时使用
ORDER BY和DUPLICATE KEY,DUPLICATE KEY不生效 - 如果两者都未使用,默认取表的前三列作为排序键
- 排序键构建 Prefix Index 加速查询
2.3 数据写入过程
- 数据按批次导入(Stream Load / Broker Load / Routine Load 等)
- 每批数据按排序键排序后写入数据文件
- 数据追加写入,不修改已有数据
- 相同键值的记录全部保留,不做合并
2.4 数据读取过程
- 根据查询条件,利用排序键和 Prefix Index 快速定位数据
- 读取数据文件中的数据
- 无需合并多版本,直接返回结果
2.5 适用场景
- 原始日志分析(如访问日志、操作记录)
- 时序数据写入(仅追加,不更新历史)
- 多维度灵活查询,不受预聚合方式限制
- 需要保留完整原始明细数据的场景
2.6 设计取舍
| 优势 | 劣势 |
|---|---|
| 完整保留原始数据,无损 | 不支持更新和删除 |
| 写入性能最优(无合并开销) | 相同键值数据冗余存储 |
| 查询方式灵活,不受预聚合限制 | 数据量可能较大 |
| 支持所有列创建 Bitmap/Bloom Filter 索引 | --- |
2.7 关键参数
DUPLICATE KEY/ORDER BY:定义排序键- 自 v3.1 起支持 Random Bucketing(默认),无需指定 HASH 分桶键
- 自 v2.5.7 起自动设置 BUCKETS 数量
- 支持在所有列上创建 Bitmap 索引和 Bloom Filter 索引
参考:https://docs.starrocks.io/docs/table_design/table_types/duplicate_key_table/
三、Aggregate 表(聚合模型)
3.1 原理与机制
- 建表时定义聚合键(Aggregate Key),并为值列指定聚合函数
- 当多行数据具有相同聚合键时,值列的数据被聚合
- 数据在三个阶段被多次聚合:
- 导入阶段:同一批次中相同聚合键的数据被聚合
- 后台 Compaction 阶段:多个版本文件合并时,相同聚合键数据再次聚合
- 查询阶段:跨版本相同聚合键数据最终聚合后返回结果
3.2 排序机制
- 建表时通过
AGGREGATE KEY定义聚合键(同时也是默认排序键) - 自 v3.3.0 起,排序键与聚合键解耦,支持通过
ORDER BY独立定义排序键 - 排序键和聚合键的列集合需相同,但列的顺序可以不同
- 排序键列在聚合前过滤,值列在聚合后过滤 → 建议高频过滤列作为排序键
- 排序键构建 Prefix Index 加速查询
3.3 数据写入过程
- 数据按批次导入,每批形成一个数据版本
- 同一版本内,相同聚合键的数据按指定聚合函数聚合
- 聚合后的数据按排序键排序写入数据文件
- 后台 Compaction 时,多个版本文件合并,相同聚合键数据再次聚合
3.4 数据读取过程
- 根据查询条件,利用排序键和 Prefix Index 快速定位数据
- 排序键列的过滤在聚合前执行
- 跨版本读取数据时,相同聚合键的数据按聚合函数合并
- 值列的过滤在聚合后执行
- 返回最终聚合结果
3.5 聚合函数类型
内置聚合函数:
SUM:求和,适用于数值累加场景MAX:最大值,适用于取最新状态MIN:最小值,适用于取最早状态REPLACE:替换,用新值替换旧值HLL_UNION:HyperLogLog 联合,用于近似去重计数PERCENTILE_UNION:百分位数联合BITMAP_UNION:位图联合,用于精确去重计数
通用聚合函数状态(v3.4+,Beta):
- 支持所有内置聚合函数的中间状态存储
- 定义方式:
col_name agg_func_name(parameter1_type, [parameter2_type], ...) - 示例:
avg(bigint)、array_agg(int)、ds_hll_count_distinct(varchar) - 通过
_state/_union/_merge组合函数实现中间状态流转 - 可用于同步物化视图和异步物化视图
3.6 适用场景
- 网站流量统计(PV/UV)
- 广告点击量/曝光量统计
- 电商分时段/分区销售汇总
- 查询以聚合为主(SUM/MAX/MIN),不需要原始明细
- 历史数据不频繁更新,仅追加新数据
3.7 设计取舍
| 优势 | 劣势 |
|---|---|
| 减少存储数据量,查询效率高 | 丢失原始明细数据,无法回溯 |
| 导入即聚合,查询时聚合量小 | 只能更新全部列,不支持部分列更新 |
| 支持多种聚合函数 | 值列只能通过聚合函数访问 |
| v3.4 支持通用聚合函数状态 | 聚合键具有唯一性约束 |
3.8 关键参数
AGGREGATE KEY:定义聚合键,必须在其值列之前ORDER BY(v3.3+):独立定义排序键,列集合需与聚合键相同但顺序可不同- 仅支持在 Key 列上创建 Bitmap/Bloom Filter 索引
- 导入时只能更新全部列
参考:https://docs.starrocks.io/docs/table_design/table_types/aggregate_table/
四、Unique Key 表(唯一键模型)--- Merge-on-Read
4.1 原理与机制
- 可视为特殊的聚合模型,值列使用 REPLACE 聚合函数
- 相同唯一键的多版本数据,查询时返回最大版本号的记录
- 采用 Merge-on-Read 策略:写入时简单高效,读取时需在线合并多版本数据文件
- 正在被 Primary Key 表逐步替代
4.2 排序机制
- 建表时通过
UNIQUE KEY定义唯一键(同时也是默认排序键) - 自 v3.3.0 起,排序键与唯一键解耦,支持通过
ORDER BY独立定义排序键 - 排序键和唯一键的列集合需相同,但列的顺序可以不同
- 排序键构建 Prefix Index 加速查询
- 查询时排序键列的过滤在合并前执行,值列的过滤在合并后执行
4.3 数据写入过程
- 数据分批导入,每批分配版本号
- 相同唯一键的记录可能存在于多个版本中
- 写入时简单追加,不做在线合并
- 后台 Compaction 阶段合并多版本文件
4.4 数据读取过程
- 根据查询条件,利用排序键定位数据
- 需在线合并多版本数据:对于相同唯一键的记录,取最大版本号的记录返回
- Merge 操作阻止谓词和索引下推到底层数据
- 版本数越多,查询性能越差
4.5 适用场景
- 电商订单状态实时更新(数百亿订单,状态频繁变更)
- 需要实时频繁数据更新的业务场景
- 对查询延迟要求不极致的更新场景
4.6 设计取舍
| 优势 | 劣势 |
|---|---|
| 支持实时频繁更新 | 查询时需聚合多版本,性能受版本数影响 |
| 写入简单高效 | Merge 操作阻止谓词和索引下推 |
| 保证最新数据可见 | 大量版本严重降低查询性能 |
| --- | 只能更新全部列,不支持部分列更新 |
| --- | 逐步被 Primary Key 表替代 |
4.7 关键参数与建议
UNIQUE KEY:定义唯一键,必须在其值列之前ORDER BY(v3.3+):独立定义排序键- 建议控制导入频率,避免过多版本(如需分钟级数据,导入频率设为 1 分钟而非 1 秒)
- 仅支持在 Key 列上创建 Bitmap/Bloom Filter 索引
- 只能更新全部列
参考:https://docs.starrocks.io/docs/table_design/table_types/unique_key_table/
五、Primary Key 表(主键模型)--- Delete+Insert(Merge-on-Write)
5.1 原理与机制
- 使用 StarRocks 专门设计的新存储引擎
- 采用 Delete+Insert 策略(Merge-on-Write),而非 Merge-on-Read
- 核心机制:主键索引 + DelVector(删除标记向量)
- 主键具有 UNIQUE + NOT NULL 约束
- 自 v3.0 起排序键与主键解耦
- 自 v3.1 起支持 shared-data 集群
- 自 v3.1.4 起支持持久化索引到本地磁盘
- 自 v3.3.2 起支持持久化索引到对象存储
5.2 排序机制
- 自 v3.0 起,排序键与主键解耦,通过
ORDER BY独立定义 - 排序键可由任意列组合构成
- 数据导入时按排序键排序后存储
- 排序键构建 Prefix Index 加速查询
- 如果未指定排序键,Prefix Index 基于主键构建
- 建表后可通过
ALTER TABLE ... ORDER BY ...修改排序键
5.3 数据写入过程
- StarRocks 内部 Loadjob 接收一批数据变更操作(Insert/Update/Delete)
- 将对应 Tablet 的主键索引加载到内存
- DELETE 操作:通过主键索引定位原始行位置(数据文件+行号),在 DelVector 中标记为已删除
- UPDATE 操作:先标记旧行删除(DelVector),再将新行写入新数据文件(Delete+Insert)
- 主键索引同步更新,记录新行位置
- 数据按排序键排序后写入
5.4 数据读取过程
- 历史重复记录已在写入时标记删除,只需读取最新行
- 无需在线合并多版本数据文件
- 谓词和索引可以下推到底层数据
- 过滤算子和各种索引减少扫描开销
- 查询性能比 Unique Key 的 Merge-on-Read 提升 3-10 倍
5.5 与 Unique Key (MoR) 对比
| 特性 | Unique Key (MoR) | Primary Key (MoW) |
|---|---|---|
| 写入策略 | 追加多版本 | Delete+Insert |
| 读取时合并 | 需要 | 不需要 |
| 谓词/索引下推 | 受限(需先合并) | 完全支持 |
| 查询性能 | 受版本数影响 | 稳定高效(3-10x 提升) |
| 内存消耗 | 低 | 需主键索引(可持久化) |
| 部分列更新 | 不支持 | 支持 |
| 更新方式 | 只能更新全部列 | 支持部分列更新 |
5.6 主键约束
- PRIMARY KEY 列具有 UNIQUE + NOT NULL 约束
- 主键列必须在其值列之前定义
- 主键列必须包含分区列和分桶列
- 支持数据类型:数值(整数和 BOOLEAN)、字符串、日期(DATE 和 DATETIME)
- 主键编码后最大长度默认 128 字节
- 建表后不可修改主键
- 主键值不可更新(为保持数据一致性)
- 支持 AUTO_INCREMENT 列作为主键
5.7 主键索引
持久化索引 (enable_persistent_index = true,默认):
- 仅小部分索引在内存,大部分存储在磁盘
- SSD 推荐开启;HDD 低频加载也可开启
- v3.1.4+ shared-data 支持持久化到本地磁盘
- v3.3.2+ shared-data 支持持久化到对象存储(
persistent_index_type = CLOUD_NATIVE) - 查询和更新性能与全内存索引几乎等同
全内存索引 (enable_persistent_index = false):
- 全部主键索引加载到内存
- 适用于内存充足、数据量适中的场景
5.8 适用场景
- 实时数据流同步:从事务处理系统(MySQL等)通过 CDC 实时同步数据到 StarRocks,支持实时增删改,查询性能比 Unique Key 提升 3-10 倍
- 多流 Join + 部分列更新:用户画像场景,上游数据来自多个应用(购物/外卖/银行等),各应用只更新自己业务范围内的列
5.9 关键参数
PRIMARY KEY:定义主键ORDER BY:定义排序键(v3.0+)enable_persistent_index:是否持久化主键索引(默认 true)persistent_index_type:持久化索引类型(CLOUD_NATIVE,v3.3.2+)- 只支持 Hash 分桶(
DISTRIBUTED BY HASH) - 支持 AUTO_INCREMENT 列作为主键
参考:https://docs.starrocks.io/docs/table_design/table_types/primary_key_table/
六、四种模型对比总结
| 特性 | Duplicate Key | Aggregate | Unique Key | Primary Key |
|---|---|---|---|---|
| 数据合并策略 | 无(Append-Only) | 导入+Compaction+查询聚合 | Merge-on-Read | Delete+Insert (MoW) |
| 更新支持 | 不支持 | 仅全列替换 | 全列 REPLACE | 支持部分列更新 |
| 删除支持 | 不支持 | 不支持 | 支持 | 支持 |
| 查询性能 | 优(无合并开销) | 良(预聚合减少数据量) | 受版本数影响 | 优(3-10x vs MoR) |
| 数据完整性 | 完整保留原始 | 仅保留聚合结果 | 仅保留最新 | 仅保留最新 |
| 索引范围 | 所有列 | 仅 Key 列 | 仅 Key 列 | 所有列 |
| 内存开销 | 低 | 低 | 低 | 中(主键索引) |
| 排序键独立性 | v3.3+ ORDER BY | v3.3+ ORDER BY | v3.3+ ORDER BY | v3.0+ ORDER BY |
| 分桶方式 | Random/Hash | Hash | Hash | 仅 Hash |
| 推荐场景 | 日志/时序 | 统计汇总 | 逐步淘汰 | 实时更新/用户画像 |
七、选型决策树
- 是否需要更新/删除数据?
- 否 → Duplicate Key(明细模型)
- 是 → 继续
- 更新模式是什么?
- 仅聚合查询,不需原始明细 → Aggregate(聚合模型)
- 需要保留最新完整记录 → 继续
- 对查询性能要求?
- 极致查询性能 + 实时更新 → Primary Key(主键模型,推荐)
- 可接受查询时的合并开销 → Unique Key(唯一键模型,逐步淘汰)
- 特殊需求?
- 多流部分列更新(用户画像) → Primary Key
- CDC 实时同步 → Primary Key
八、参考链接
- 表类型概览:https://docs.starrocks.io/docs/table_design/table_types/
- Duplicate Key 表:https://docs.starrocks.io/docs/table_design/table_types/duplicate_key_table/
- Aggregate 表:https://docs.starrocks.io/docs/table_design/table_types/aggregate_table/
- Unique Key 表:https://docs.starrocks.io/docs/table_design/table_types/unique_key_table/
- Primary Key 表:https://docs.starrocks.io/docs/table_design/table_types/primary_key_table/
- 数据分布:https://docs.starrocks.io/docs/table_design/data_distribution
- 索引设计:https://docs.starrocks.io/docs/table_design/indexes/
- GitHub 源码:https://github.com/StarRocks/starrocks