Doris 数据划分实战:List 分区、分桶列与桶数选择

1. List 分区示例:按地区划分数据

List 分区适合取值集合明确、离散的字段,例如地区、业务线、租户类型等。与 Range 分区按连续区间切分不同,List 分区通过枚举值精确匹配,只有命中枚举值的数据才能写入对应分区。

sql 复制代码
CREATE TABLE IF NOT EXISTS demo.user_visit_list
(
    `user_id`     BIGINT      NOT NULL COMMENT '用户 ID',
    `dt`          DATE        NOT NULL COMMENT '业务日期',
    `city`        VARCHAR(32) NOT NULL COMMENT '城市',
    `visit_count` BIGINT      SUM DEFAULT '0' COMMENT '访问次数'
)
ENGINE = OLAP
AGGREGATE KEY(`user_id`, `dt`, `city`)
PARTITION BY LIST(`city`)
(
    PARTITION `p_north` VALUES IN ('Beijing', 'Tianjin'),
    PARTITION `p_east`  VALUES IN ('Shanghai', 'Hangzhou'),
    PARTITION `p_south` VALUES IN ('Guangzhou', 'Shenzhen')
)
DISTRIBUTED BY HASH(`user_id`) BUCKETS 4
PROPERTIES
(
    "replication_num" = "1"
);

只有 city 命中某个分区枚举值时,数据才能写入。例如 Beijing 会进入 p_north,而没有定义的 Chengdu 无法命中以上任何分区,写入会失败。

1.1 增加一个西部地区分区

sql 复制代码
ALTER TABLE demo.user_visit_list
ADD PARTITION `p_west` VALUES IN ('Chengdu', 'Chongqing')
DISTRIBUTED BY HASH(`user_id`) BUCKETS 4;

1.2 删除一个分区

sql 复制代码
ALTER TABLE demo.user_visit_list
DROP PARTITION `p_east`;

删除分区会连同该分区内的全部数据一起移除,因此在大批量历史数据清理场景中,删分区通常比逐行 DELETE 更高效。

2. 分桶列与桶数怎么选

2.1 分桶列

分桶列通常选择:

  • 经常出现在等值查询条件中的列,例如 WHERE user_id = 1001;
  • 基数较高、取值较均匀的列;
  • 不容易造成大量数据集中到少数桶中的列。

本例选择:

sql 复制代码
DISTRIBUTED BY HASH(`user_id`) BUCKETS 4

相同 user_id 会通过稳定的 Hash 规则落入对应桶中。分区表的 Hash 分桶规则会在每个分区内部分别应用,因此本例每个分区都有 4 个 Tablet。

2.2 桶数

本地练习可从 1~4 个桶开始:

  • 数据很少、只验证语法:1 个桶即可;
  • 想观察 Tablet 和分桶:可使用 4 个桶;
  • 不要因为生产环境桶数较多,就在单机小数据测试中照搬几十或几百个桶。

如果 Range 表有 3 个分区、每个分区 4 个桶、副本数为 1,则可近似理解为:

text 复制代码
3 个 Partition × 4 个 Tablet × 1 个 Replica = 12 个 Tablet 副本

这些副本全部存放在唯一的 BE 上,因此增加桶数不会带来跨 BE 的并行能力或高可用能力。

3. 多列分区

Doris 支持使用多列进行 Range 或 List 分区。比较时按列顺序进行,理解和维护成本更高,入门阶段建议优先使用单列分区。

多列 List 示例:

sql 复制代码
PARTITION BY LIST(`tenant_id`, `city`)
(
    PARTITION `p1` VALUES IN (('1', 'Beijing'), ('1', 'Shanghai')),
    PARTITION `p2` VALUES IN (('2', 'Beijing'), ('2', 'Shanghai'))
)

4. 什么时候使用"分区 + 分桶"

适合使用两层划分的常见场景:

  1. 按时间管理数据:按天或按月建分区,查询时利用分区裁剪。
  2. 定期清理历史数据:直接删除过期分区,比逐行删除更适合大批量历史数据清理。
  3. 不同周期数据量差异较大:可为不同分区规划不同桶数。
  4. 需要控制单个 Tablet 的数据量:在分区内部继续分桶,避免一个逻辑分片过大。

如果表非常小、没有历史分区管理需求,可以不显式分区,只保留 Hash 分桶。

5. 查看与验证

查看 BE 节点:

sql 复制代码
SHOW BACKENDS;

查看建表语句:

sql 复制代码
SHOW CREATE TABLE demo.user_visit_range;

查看分区:

sql 复制代码
SHOW PARTITIONS FROM demo.user_visit_range;

查看 Tablet 分布:

sql 复制代码
SHOW TABLETS FROM demo.user_visit_range;

验证分区裁剪:

sql 复制代码
EXPLAIN
SELECT SUM(visit_count)
FROM demo.user_visit_range
WHERE dt >= '2026-02-01'
  AND dt <  '2026-03-01';

在 EXPLAIN 结果中,如果 partitions 只列出 2 月对应的分区,说明分区裁剪已生效,查询不会扫描无关分区。

相关推荐
BK贝壳8 小时前
亿级用户签到位图选型复盘:用 bool-hybrid-array 扛冷启动打卡,也把它和 Roaring/Redis 的边界测清楚了
数据结构·python·性能优化·numpy
挖井观天17 小时前
《Java数据结构》第一讲:顺序表
数据结构
炘爚18 小时前
数据结构算法总结
数据结构·python·算法
见叶之秋19 小时前
【C++】红与黑的边界:红黑树从插入到自检
数据结构·c++·算法·面试
kiracrimson20 小时前
string 容器:从 C 字符串到会自己扩容的类
开发语言·数据结构·c++·stl
CQU_JIAKE1 天前
10.25【A】
数据结构·算法
海清河晏1111 天前
加油站问题
数据结构·算法·leetcode
GG.WinGel1 天前
质数数目(蓝桥杯练习题)
java·数据结构·算法·青少年编程·蓝桥杯
敲代码的苦131 天前
头歌 数据结构—消防资源调度
数据结构·算法