排序键与聚簇键的选择
排序键与聚簇键决定数据在存储里的物理顺序,直接影响扫描量与 join 代价。选择原则是看高频查询的过滤与关联列:日期范围过滤、用户或商品等值关联是最常见的两类。高基数的等值列适合放在前面,低基数的枚举列打头会让裁剪效果大幅衰减。需要注意的是调整排序键通常意味着重写历史数据,因此要把重写成本与收益一并评估后再动手。
基本信息
| 选择优先级 | 高频过滤列 + 高频 join 列 |
|---|---|
| 排列原则 | 高基数等值列优先,低基数枚举避免打头 |
| 收益体现 | 扫描数据量下降、join 与聚合更快 |
| 变更成本 | 调整键通常需要重写历史数据,需评估窗口 |
典型使用场景
- 日报表加速:按日期与门店过滤,排序键设为日期在前
- 关联加速:事实与维度按同一键聚簇,减少 shuffle 数据量
- 数据倾斜缓解:用高基数列打散热点,改善并行度
- 存储优化:合理排序提升压缩率,降低长期存储成本
- 性能回归排查:查询变慢时先核对排序键是否仍匹配查询模式
键选择示例
键选择示例
-- 常用查询:按日期范围 + 门店过滤,并在门店维度上关联
-- 聚簇键设计:(date_key, shop_sk)
-- date_key 在前:支撑时间范围裁剪
-- shop_sk 在后:支撑按门店过滤与关联
CLUSTERED BY (date_key, shop_sk) SORTED BY (date_key) INTO 128 BUCKETS
-- 反例:低基数枚举打头,过滤后仍需扫描大部分数据
-- CLUSTERED BY (is_weekend, order_type)
-- 变更评估:调整键后历史分区需重写,先估算数据量与重写窗口键选择对照
| 查询模式 | 推荐键顺序 | 原因 |
|---|---|---|
| 按日期范围过滤 | date_key 打头 | 支撑分区与排序裁剪 |
| 按高基数列等值过滤 | 该列打头 | 快速定位数据块 |
| 双列常用组合 | 过滤列在前,关联列在后 | 先缩小范围再关联 |
| 低基数枚举过滤 | 不放在首位 | 裁剪收益低,浪费排序位 |
排序键与查询模式脱节时,效果是扫描量不下降但也不报错,容易被误判为引擎能力不足,实际是设计问题。
排序键不是越多越好:多加一列会削弱前面的裁剪效果并增加写入开销,通常两三列覆盖主要查询即可。