维度表存储怎么优化
维度表的存储选型要和它的使用方式匹配:小维度(行数在几万以内)用单文件紧凑格式,不必分区;版本化的大维度按 is_current 或更新时间分区,让「取当前版本」的查询只扫一个分区;文件格式统一用 ORC 或 Parquet 加压缩;同时控制小文件数量,避免小查询把时间耗在文件打开上。
基本信息
| 小维度 | 不分区分桶,合并为单文件或少量文件 |
|---|---|
| 版本化大维度 | 按 is_current 或更新时间分区 |
| 文件格式 | ORC / Parquet + 压缩(如 snappy、zstd) |
| 分桶 | 大维度可按常用 join 键分桶 |
| 小文件治理 | 周期性合并或按分区重写 |
| 常见引擎 | Hive / Spark SQL,配置项随版本略有差异 |
典型使用场景
- 当前版本查询加速:按 is_current 分区,只扫当前分区
- 历史版本归档:旧版本单独分区,降低日常扫描量
- 减少小文件:维度每日全量覆盖会产生大量小文件,需周期合并
- join 优化:大维度按 join 键分桶,减少 shuffle
- 成本控制:冷维度降低压缩成本或换更冷存储
按当前标志分区
按当前标志分区
CREATE TABLE dim_customer (
customer_sk bigint,
customer_id string,
name string,
start_date date,
end_date date
)
PARTITIONED BY (is_current int) -- 当前版本与历史版本分开存放
STORED AS ORC; -- 列式存储 + 压缩,适合宽维度的部分列读取存储选择对照
| 维度类型 | 推荐做法 | 注意点 |
|---|---|---|
| 小维度(万行级) | 单文件、不分区 | 文件数少但别频繁改写 |
| 版本化大维度 | 按 is_current 分区 | 当前分区大小要可控 |
| 超大文本维度 | ORC/Parquet + 字典编码 | 字符串列压缩效果最好 |
| 高频 join 维度 | 按 join 键分桶 | 分桶数要与下游一致 |
is_current 分区能让当前版本查询只扫一个分区,而历史查询仍可全扫;缺点是每次版本切换都要重写分区,因此要结合版本变更频率决定是否值得。
维度表每天全量覆盖写入会产生大量小文件:应按周期(例如每周)做一次合并重写,并注意重写期间下游查询的可见性,通常用临时表写好后整体替换。