首页/数据/数仓建模速查/维度拉平与非规范化
维度与事实设计149 条

维度拉平与非规范化

星型模型维度按查询友好拉平:把雪花化码表 join 进维度或建层内视图,用适度冗余换取查询简洁与 join 次数减少。

数仓建模速查数据更新于 2026-10-13

维度拉平是什么

维度拉平(非规范化)指把雪花模型里挂着的码表字段直接并入维度表,或至少在层内用视图把码表 join 好,让上层看到一张宽维表。星型模型靠这一步把多次 join 收敛成一次:原本要连城市表、等级表、渠道表,现在从维表里直接读。代价是冗余存储与更宽的更新范围,换来的是查询简洁、join 次数减少、口径集中。

基本信息

手段码表的名称类字段并进维表,码值仍保留
收益减少 join,SQL 更短,跨表口径一致
代价冗余存储;码表改名要重刷维表
边界高频变更的码表谨慎拉平
配套码值列保留 + 名称列冗余,便于追源

典型使用场景

  • 星型模型落地:把雪花结构的码表合并进维表,供 BI 直接查询
  • 自助分析:业务人员只连一张维表就能拿到全部可读属性
  • 性能优化:高频报表减少 join 次数,扫描与规划开销下降
  • 口径集中:城市名称、等级名称的写法只在维表里出现一次
  • 快照留档:报表需要当时的名称而非当前码表值,冗余才有意义
  • 小码表治理:几十行的字典表拉平几乎无代价,收益明显

拉平写法

拉平写法
-- 拉平后:城市与等级名称已冗余进 dim_user
SELECT d.user_name, d.city_name, d.tier_name
FROM   dim_user d
WHERE  d.is_current = 1;

-- 拉平时的构造(层内统一完成,上层不再 join 码表)
INSERT INTO dim_user
SELECT u.user_sk, u.user_id, u.name, u.city_code, c.city_name,
       u.tier_code, t.tier_name
FROM   ods_user u
LEFT JOIN dim_city c ON u.city_code = c.city_code
LEFT JOIN dim_tier t ON u.tier_code = t.tier_code;

拉平决策对照

码表特征建议原因
行数几十到几千、低频变更拉平冗余小,查询收益大
行数上万且每月改名不拉平,保留雪花重刷成本高,易与其他副本分叉
名称需还原历史当时值拉平并做版本当前值无法体现历史口径
码表本身需多语言拉平主语言 + 字典取其他否则维表行数成倍膨胀
层级结构需上钻保留层级键或父子维拉平会丢掉结构
拉平之后码表改名必须能同步回维表,通常由统一调度重刷解决;若靠人工同步,迟早出现维表里名称是旧的、码表里是新的。拉平字段与其他表的副本必须只有一个权威来源。

易错点

  • 对高频变更码表做拉平:每次码表改名就要重刷整张维表,成本远超收益
  • 拉平字段与其他维表副本并存且各自维护:同一城市两种写法,口径分叉
  • 只冗余名称不留码值:码表改名后无法回溯当时对应的码,历史分析断链
  • 拉平后忘记重刷:码表改了维表没改,报表显示的仍是旧名称
  • 把层级结构一起压平:上钻下钻需要的信息丢失,只能回退到雪花结构

数据来源与参考

  • 数据仓库工具箱:星型模型
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌