宽表设计是什么
宽表把常用的维度属性与度量拼到同一张表里,让查询不必反复关联维表,交付效率与口径集中度都更高。代价是存储放大与更新耦合:维度属性一变,宽表要回刷;字段加得越多,回刷一次越贵。因此它适合变化频率低、复用度高的核心主题,不适合承载所有临时字段与长尾需求。
基本信息
| 收益 | 查询免连接、口径集中、交付快 |
|---|---|
| 代价 | 存储放大、维度更新需回刷 |
| 适合场景 | 高频复用的核心分析主题(交易、用户、商品) |
| 不适合 | 临时字段、一次性需求、变更频繁的长尾指标 |
| 字段治理 | 每个字段标明来源表与更新责任人 |
| 扩展节奏 | 分批扩展并保留回滚版本,避免一次大改 |
典型使用场景
- 核心主题交付:交易、用户等高频查询主题做宽表化,减少重复关联
- 报表提速:BI 直接查宽表,避免每次分析都拼多张维度表
- 口径集中:把常用指标集中在一处计算,减少各报表各写一套
- 自助分析支撑:业务同学不熟悉维表关系时可直接使用宽表
- 降低下游复杂度:把退化维度提前做好,下游只需过滤与聚合
宽表构建
宽表构建
INSERT OVERWRITE TABLE dws_trade_user_wide_1d PARTITION (dt = '2026-10-11')
SELECT o.user_id,
u.city, -- 退化维度:用户城市
u.level, -- 退化维度:会员等级
o.category, -- 退化维度:商品类目
COUNT(DISTINCT o.order_id) AS order_cnt,
SUM(o.pay_amount) AS pay_amt
FROM dwd_trade_order_detail_di o
LEFT JOIN dim_user u ON o.user_sk = u.user_sk AND u.is_current = 1
WHERE o.dt = '2026-10-11'
GROUP BY o.user_id, u.city, u.level, o.category;一致性与膨胀检查
一致性与膨胀检查
-- 关联维表未限当前版本会造成行数膨胀(一个实体多条版本)
SELECT COUNT(1) AS rows_cnt,
COUNT(DISTINCT user_id) AS user_cnt
FROM dws_trade_user_wide_1d WHERE dt = '2026-10-11';
-- 行数与用户数差异异常大时,先查维表是否未过滤当前生效版本
-- 与明细层核对总额,确认宽表加工未丢行或重复
SELECT SUM(pay_amt) FROM dws_trade_user_wide_1d WHERE dt = '2026-10-11';宽表与维表分工
| 内容 | 放宽表 | 放维表 |
|---|---|---|
| 高频过滤属性 | 适合,避免每次关联 | 也可以,但查询需连接 |
| 低频长尾属性 | 不适合,徒增回刷成本 | 适合,按需关联 |
| 度量 | 适合,聚合结果集中 | 不适合,维表不放度量 |
| 频繁变更属性 | 不适合,回刷代价高 | 适合,维表改造影响面小 |
| 多主题共用属性 | 视复用度决定 | 适合,作为一致性维度共用 |
宽表字段要能说清来源与更新责任:字段越多回刷成本越高,建议分批扩展并保留可回滚的上一个版本,避免一次大改无法回退。
关联维表务必限定当前生效版本(如 is_current 标记或生效区间):不限版本时一个实体匹配到多条历史记录,宽表行数膨胀、指标翻倍,且这类问题往往到对账时才被发现。