
做Doris开发的同学,几乎都踩过表模型的坑:
“用聚合表查用户明细,翻遍结果都找不到单条记录”“主键表做日报统计,跑了5分钟还没出结果”“明细表存订单数据,重复数据堆成山还没法去重”……
其实问题根源很简单:没吃透Doris的表模型——明细表(Duplicate Key Table)、主键表(Unique Key Table)、聚合表(Aggregate Key Table)。这3种模型没有“好坏”之分,只看“适配与否”,选对模型能让查询速度提升数倍,选错则可能让集群性能大打折扣,甚至不适配业务。
今天这篇选型指南,把3种表模型的“底层逻辑、创建方式、场景边界”一次性讲透,确保你建表时“一选即中”。
很多人混淆表模型,本质是没抓住核心差异点:如何处理数据重复和是否预聚合数据。这两个点直接决定了数据的存储方式、查询性能和适用场景,建表前先把这个表格刻在脑子里:
表模型 | 核心特征 | 数据存储逻辑 | 查询优势 | 核心局限 |
|---|---|---|---|---|
明细表(Duplicate Key) | 允许Key重复,保留全量原始数据 | 按指定Key排序存储,写多少存多少,不聚合不去重 | 支持任意维度Ad-hoc查询,列存优势明显(只读所需列) | 无预聚合,聚合查询速度慢,存储开销大 |
主键表(Unique Key) | Key唯一,只保留最新版本数据 | 按主键去重,新数据覆盖旧数据,后台清理历史版本 | 支持高频更新、部分列更新,保证数据唯一性 | 不支持ROLLUP预聚合,聚合查询性能一般 |
聚合表(Aggregate Key) | 按Key预聚合,只存聚合结果 | 写入时自动按Key分组,指标列执行预聚合(SUM/MAX等) | 聚合查询速度极快,存储开销小 | 不保留原始数据,Ad-hoc查询能力弱,count(*)不友好 |
★重要提醒:Doris表类型一旦创建无法修改!建表前必须和业务、产品确认清楚“数据是否要原始记录、是否要唯一约束、是否要高频更新”这三个核心问题。
新手最容易误解“Duplicate Key”——它不是“去重键”,而是“排序键”。数据写入时会按该Key排序存储,目的是优化查询过滤效率,而非去重。比如指定“dt+user_id”为排序键,相同user_id的记录会集中存储,查该用户数据时能快速定位范围。
场景:存储用户行为日志(需保留全量原始记录,支持多维度临时查询)
CREATE TABLE user_behavior_duplicate (
dt DATECOMMENT'日期(排序键列,高频过滤)',
user_id BIGINTCOMMENT'用户ID(排序键列,高频过滤)',
action_type VARCHAR(20) COMMENT'行为类型:点击/下单/支付',
goods_id BIGINTCOMMENT'商品ID(高频过滤,建布隆索引)',
action_time DATETIME COMMENT'行为时间',
device_id VARCHAR(50) COMMENT'设备ID(高频过滤,建布隆索引)',
channel VARCHAR(30) COMMENT'来源渠道'
)
DISTRIBUTEDBYHASH (dt, user_id) BUCKETS 10
DUPLICATEKEY (dt, user_id)
PROPERTIES (
"replication_num" = "3"
);
主键表的核心是“唯一性约束+版本管理”。指定的Unique Key是真正的主键,会强制保证唯一性;数据写入时,相同主键的记录会自动覆盖旧版本,后台通过Compaction机制清理历史版本(注意区分读时合并和写时合并),兼顾更新效率和存储开销。
它最实用的特性是“部分列更新”——比如订单表只需更新“状态”和“支付时间”,不用传全量字段,大幅提升更新效率。
场景:电商订单表(订单ID唯一,需高频更新状态)
CREATE TABLE order_unique (
order_id BIGINTCOMMENT'订单ID(主键,唯一标识,不可更新)',
user_id BIGINTCOMMENT'用户ID',
goods_id BIGINTCOMMENT'商品ID',
order_amt DECIMAL(16,2) COMMENT'订单金额(静态列,很少更新)',
order_status TINYINTCOMMENT'订单状态:0-待支付,1-已支付,2-已取消(高频更新列)',
create_time DATETIME COMMENT'创建时间(静态列)',
pay_time DATETIME COMMENT'支付时间(高频更新列)',
operatorVARCHAR(50) COMMENT'操作人'
)
DISTRIBUTEDBYHASH (order_id) BUCKETS 30
UNIQUEKEY (order_id)
PROPERTIES (
"replication_num" = "3"
);
聚合表的核心是“写入时预聚合,查询时直接取结果”。建表时指定“聚合Key列”(维度列)和“指标列”(带聚合函数),数据写入时就自动按Key分组聚合,旧数据会被聚合后的结果覆盖——比如100条同一商品的订单记录,最终只存1条“商品ID+总销量”的聚合数据。
它的优势是“存储量小、聚合查询快”,但代价是“丢失原始数据”,只适合固定维度的报表查询。
场景:电商运营日报表(按天+商品维度统计,支持运营看板秒级查询)
CREATE TABLE goods_sales_aggregate (
dt DATECOMMENT'日期(聚合Key列,维度)',
goods_id BIGINTCOMMENT'商品ID(聚合Key列,维度)',
goods_name VARCHAR(100) COMMENT'商品名称(聚合Key列,维度,需和Key列一起聚合)',
categoryVARCHAR(50) COMMENT'商品分类(聚合Key列,维度)',
order_cnt SUMBIGINTCOMMENT'下单数量(指标列,求和)',
sales_amt SUMDECIMAL(16,2) COMMENT'销售金额(指标列,求和)',
max_price MAXDECIMAL(10,2) COMMENT'最高单价(指标列,取最大)',
pay_user_cnt COUNT(DISTINCT) BIGINTCOMMENT'支付用户数(指标列,去重计数)'
)
DISTRIBUTEDBYHASH (dt, goods_id) BUCKETS 20
AGGREGATEKEY (dt, goods_id, goods_name, category)
PROPERTIES (
"replication_num" = "3"
);
业务场景 | 推荐模型 | 核心原因 |
|---|---|---|
用户行为日志分析 | 明细表 | 需保留原始日志,支持多维度Ad-hoc查询 |
电商订单管理 | 主键表 | 订单ID唯一,需高频更新状态,兼顾明细查询 |
运营日报/看板统计 | 聚合表 | 固定维度预聚合,查询速度快,支持秒级响应 |
金融交易流水存档 | 明细表 | 监管要求保留全量原始流水,需追溯单条记录 |
商品维度表(每日更新) | 主键表 | 商品ID唯一,每日更新价格、库存等信息 |
实时GMV统计 | 聚合表 | 按天+地区预聚合,支持秒级查询,存储量小 |
Doris的3种表模型,本质是为不同“数据使用场景”量身定制的工具:
很多人建表踩坑,不是模型不好用,而是“用错了场景”——比如用聚合表查明细、用主键表做统计。下次建表前,先对照决策指南过一遍,再结合建表模板调整参数,基本不会出错。
你建表时踩过表模型的坑吗?比如用错模型导致查询慢、更新失败?评论区说下你的场景,我帮你分析该换哪种模型~
往期推荐
Apache Doris 湖仓一体:打破数据边界,解锁实时分析的终极答案
Doris vs ClickHouse 企业级实时分析引擎怎么选?
完
●
数据极客圈子介绍
●
圈子1
Apache Doris社区是目前国内最活跃的开源社区(之一)。Apache Doris(Apache 顶级项目) 聚集了世界全国各地的用户与开发人员,致力于打造一个内容完整、持续成长的互联网开发者学习生态圈!
如果您对Apache Doris感兴趣,可以通过以下入口访问官方网站、社区论坛、GitHub和dev邮件组:
💡官网文档:https://doris.apache.org
💡社区论坛:https://ask.selectdb.com
💡GitHub:https://github.com/apache/doris
💡dev邮件组:dev@doris.apache.org
可以加作者微信(Faith_xzc)直接进Doris官方社区群
圈子2
PowerData是由一群数据从业人员,因为热爱凝聚在一起,以开源精神为基础,组成的数据开源社区。
社区群内会定期组织模拟面试、线上分享、行业研讨、线下Meetup、城市聚会、求职内推等活动,同时在社区群内你可以进行技术讨论、问题请教,结识更多志同道合的数据朋友。
社区整理了一份每日一题汇总及社区分享PPT,内容涵盖大数据组件、编程语言、数据结构与算法、企业真实面试题等各个领域,帮助您提升自我,成功上岸。
可以加作者微信(Faith_xzc)直接进PowrData官方社区群
叮咚✨ “数据极客圈” 向你敞开大门,走对圈子跟对人,行业大咖 “唠” 数据,实用锦囊天天有,就缺你咯!快快关注数据极客圈,共同成长!
点击上方公众号关注我们