TL;DR
- 场景: Cube 维度数量多,Cuboid 指数增长导致构建慢、存储膨胀
- 结论: 通过衍生维度 + 聚合组 + 膨胀率监控,可有效控制 Cuboid 数量
- 产出: Cuboid 检查工具、衍生维度配置、膨胀率分析、错误速查
Cuboid 剪枝概述
什么是 Cuboid
Cuboid 特指 Kylin 中在某一种维度组合下所计算的所有数据。以减少 Cuboid 数量为目的的优化统称为 Cuboid 剪枝。
Cuboid 数量计算
4 个维度:2^4 = 16 个 Cuboid
10 个维度:2^10 = 1024 个 Cuboid
20 个维度:2^20 = 1048576 个 Cuboid
剪枝原则
- 跳过永远不会查询的 Cuboid
- 跳过能力与其他 Cuboid 接近的 Cuboid
- 前提:不明显影响查询时间
检查 Cuboid 数量
CubeStatsReader 工具
# 进入 Kylin 安装目录
cd $KYLIN_HOME
# 执行 Cuboid 统计
kylin.sh org.apache.kylin.engine.mr.common.CubeStatsReader wzk_kylin_test_cube_4
输出结果
- 估计 Cuboid 大小的精度(HII Precision)
- 总共的 Cuboid 数量
- Segment 的总行数估计
- Segment 的大小估计
- 所有 Cuboid 及分析结果
检查 Cube 大小(Web GUI)
在 Model 页面选择一个 READY 状态的 Cube:
- Cube Size: Cube 实际大小
- Expansion Rate: 膨胀率 = Cube大小 / 源数据大小
膨胀率参考:
- 0% ~ 1000%:正常范围
- > 1000%:需要优化
衍生维度(Derived Dimension)
原理
将维度表的非主键字段设为衍生维度:
- 不参与 Cuboid 计算
- 使用维度表主键替代
- 查询时动态翻译
适用场景
- 维度表字段与主键有明确映射关系
- 聚合工作量不大
不适用场景
- 主键到维度需要大量聚合
- 影响查询性能
创建衍生维度
在 Kylin Cube Designer 中:
- 选择维度表
- 找到要设为衍生的列
- 勾选 Derived
- 保存 Cube
案例对比
日期维度表 dim_date:
| 字段 | 说明 |
|---|---|
| dateid | 主键 |
| dayofyear | 年中第几天 |
| dayofmonth | 月中第几天 |
| day_in_year | 年中第几天(另一种) |
| day_in_month | 月中第几天(另一种) |
| weekday | 星期几 |
| week_in_month | 月中第几周 |
| week_in_year | 年中第几周 |
| date_type | 日期类型 |
| quarter | 季度 |
注意:日期维度字段不能是 year、month 等,需要是 dim_date 表中的字段。
对比结果
| Cube 类型 | Cuboid 数量 | 构建时间 | 存储大小 |
|---|---|---|---|
| 普通维度 | 更多 | 更长 | 更大 |
| 衍生维度 | 明显更少 | 更短 | 更小 |
膨胀率高的原因
- 维度数量多,未做 Cuboid 剪枝
- 存在高基数维度(如用户ID、订单ID)
- 存在占用空间大的度量(如 Count Distinct)
错误速查
| 症状 | 根因定位 | 修复 |
|---|---|---|
| 膨胀率 > 1000% | Cuboid 过多/高基数维度/重度 Count Distinct | 检查 GUI 体积与膨胀率;使用 StatsReader 查看体积/行数分布;禁用不命中/近似 Cuboid |
| 构建极慢/失败 | 维度组合爆炸/资源与切分不匹配 | 查看构建 Job 日志;Segment 大小与 Mapper/Reducer 数强剪枝 |
| StatsReader 无输出 | 工具类路径与版本不匹配 | 在 $KYLIN_HOME 执行;校验发行包中的类名 |
| 查询变慢(启用 Derived 后) | 查询端二次聚合成本上升 | 查看查询计划/Profile;高频维度改回普通维度 |
| 某些 Cuboid 从不命中 | 设计与查询模式不符 | 查看查询日志/命中统计;在 Cube 设计中禁用该组合 |