宽表设计——什么时候该建宽表?什么时候该拆?
本文目录
先说结论
宽表的价值是『一次查询不用 JOIN』。BI 看板、交互式分析、ad-hoc 查询这些场景,宽表能把查询延迟从秒级降到毫秒级。
宽表的代价是『更新成本和存储冗余』。任何一个字段变了都要刷全表;字段多了存储几倍放大。
拆宽表的三个信号:字段超过 100 个、日更新量超过 20% 的字段、不同业务域的字段被硬塞到一张表。出现两个就该拆。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
宽表是数仓里最有争议的设计之一。年轻同学爱建宽表——一张 300 个字段的表解决所有查询;有经验的人怕宽表——因为维护噩梦。面试官问这道题想看的是:你知不知道宽表的价值、边界、以及什么时候该拆。回答『都建宽表』或『都拆小表』都是外行。真正的答案是:按业务场景决定。
业务场景:某短视频平台的用户宽表演化
我在某短视频平台做过一张用户宽表 dws_user_wide,上线时 80 个字段,两年后膨胀到 280 个字段,成了 Data Team 最大的维护黑洞——改一次 ETL 要测一整天,任何字段出错都要重跑几小时。最后我主导拆成了三张:用户画像维度、用户行为聚合、用户变现指标。拆完后每张表 60-100 个字段,职责清晰,迭代速度明显提升。
-- 拆前:dws_user_wide 280 字段一张表
CREATE TABLE dws_user_wide (
uid, register_date, country, device, ... -- 画像(50字段)
pv_7d, uv_7d, duration_7d, ... -- 行为(100字段)
gmv_7d, order_cnt_7d, coupon_used_7d, ... -- 变现(80字段)
kol_tag, risk_level, ... -- 算法标签(50字段)
); -- 单表 280 字段、跑一次 ETL 4 小时
-- 拆后:按业务域拆三张
dws_user_profile -- 画像(60 字段)
dws_user_behavior -- 行为(100 字段)
dws_user_monetize -- 变现(80 字段)
-- 下游要跨域的查询就 JOIN
SELECT p.country, SUM(m.gmv_7d)
FROM dws_user_profile p
JOIN dws_user_monetize m USING (uid, dt)
WHERE p.dt = '2024-03-15'
GROUP BY p.country;
段落一:什么时候必须建宽表
| 场景 | 为什么要宽表 | 建议字段数上限 |
|---|---|---|
| BI 看板直连 | 查询响应要秒级,JOIN 代价承受不起 | 50-80 字段 |
| ad-hoc 交互分析 | 用户点一下就要出结果 | 80-120 字段 |
| 机器学习特征工程 | 模型训练要一次取几百列 | 200-500 字段 |
| 导出到外部系统 | B2B 交付,对方不做 JOIN | 按业务需求 |
关键观察:BI 看板和 ad-hoc 分析的字段数应该控制在 100 以内,超过就要考虑拆。机器学习特征宽表例外,特征工程本来就要几百列,这是机器学习特有的范式。
段落二:什么时候该拆宽表——三个明确信号
信号一:单表字段超过 100 个。字段多不是原罪,但超过 100 个基本意味着这张表承担了多个业务域。
信号二:日更新量超过 20% 的字段。宽表的致命伤是『一个字段变了全表重写』。如果 100 个字段里 30 个每天要更新,那每天全表重写的计算成本非常高。
信号三:不同团队在改同一张表。画像组、变现组、算法组都在改同一张宽表,上线 merge 冲突不断,谁也不敢改——这种组织摩擦是拆表的最强信号。
Plain
拆表触发条件检查表:
□ 字段数 > 100?
□ 每天更新的字段 > 20%?
□ 2+ 个业务域的字段混在一起?
□ 不同团队在同一张表上改代码?
□ 单次 ETL 时长 > 2 小时?
□ 字段含义分歧、命名冲突越来越多?
命中 2+ 项就要认真考虑拆表。
段落三:拆表的三种方案对比
方案一:按业务域垂直拆分。画像、行为、变现各一张。最常见、最清晰。
方案二:按更新频率拆分。稳定字段一张、高频更新字段一张。适合宽表里字段混更新频率的场景。
方案三:按粒度水平拆分。用户日、用户周、用户月各一张。适合周期性汇总占大头的情况。
| 方案 | 适用场景 | 下游改造成本 |
|---|---|---|
| 按业务域拆 | 字段数太多、多团队维护 | 高(SQL 要加 JOIN) |
| 按更新频率拆 | 高频更新少、稳定字段多 | 低(JOIN 两张即可) |
| 按粒度拆 | 周/月聚合占查询主力 | 低(下游直接选对应粒度) |
段落四:拆表之后的规范——防止下一个宽表
拆完以后最怕的是过一年又堆成一张宽表。要建立规范:
规范一:新增字段前先问『这字段属于哪张表』。如果不属于现有任何一张,不应该往现有表里塞,应该评估是否建新表。
规范二:代码 review 卡死字段数。在团队规范里写『单表字段数超过 100 需要评审』,强制大家反思。
规范三:定期字段使用审计。每季度扒一次 SQL 日志,统计每个字段被查询的频率。长期没被查的字段 deprecate。
面试高频追问
追问一:宽表和大宽表有什么区别?
大宽表是宽表的极端形态,字段 500+、覆盖整个业务域(比如『用户全域宽表』把所有用户相关字段全放进来)。大宽表在机器学习特征场景有必要,但在 BI 场景基本是 anti-pattern——会膨胀到几百 TB、ETL 跑几小时、一个字段出错整表重跑。我的态度是:BI 场景最多到 100-120 字段,要上 500 字段就拆。
追问二:如果业务方要求『我就要一张表 JOIN 所有东西』怎么沟通?
这是真实的沟通难题。我的做法是两步:(1)给业务方提供『视图层宽表』——底层是拆开的,用视图或物化视图对外呈现成一张大宽表,业务方感知不到拆分;(2)看板平台上做预 JOIN,业务方查的是看板而不是原始表。这样两边都舒服——业务方看到的是一张表,维护方看到的是拆开的物理表。
追问三:宽表的字段怎么命名防止冲突?
三个规则:(1)加业务前缀——比如 monetize_gmv_7d、behavior_pv_7d;(2)加时间窗后缀——pv_1d / pv_7d / pv_30d;(3)建命名注册表(metadata)——所有字段命名过规范,不允许自由发挥。我在某出海硬件品牌做埋点治理时就是这套打法,1000+ 事件精简到 100+ 标准化事件,数据质量问题减少 60%。
实战踩坑:一张宽表把 3 个团队的迭代拖到每周一次
我在某短视频平台做那张 280 字段宽表时,最痛的一件事是『上线节奏被迫拉长到每周一次』——因为三个团队都在同一张表上改代码,任何一个团队上线都要先和其他团队对齐,冲突解决、回归测试、联合灰度,整个周期 3-4 天。每周只能发一次版。
拆表之后,画像、行为、变现各自独立的 ETL,互不影响,每个团队每天都可以自己上线。这个收益是技术之外最大的——组织敏捷度。面试时要能把『拆表的价值』讲到组织层面,不只停留在性能。
Plain
拆前的协作成本:
3 个团队 × 共用 1 张宽表 → 任何一个上线都要对齐
上线周期:1 周
冲突数:平均每周 2-3 次
拆后的协作成本:
3 个团队 × 各自 1 张表 → 独立上线
上线周期:按团队节奏(1-2 天)
冲突数:几乎为零
总结
宽表题考的是 trade-off 判断力。面试时能讲清楚『什么场景值得建宽表、什么信号触发拆表、拆表有几种方案』,再补一个真实的组织层面收益故事(比如拆表让三个团队独立上线),这题就拿到资深水平。最忌讳的是『宽表不好』或『宽表最好』这种一刀切答案。
下一篇:『拉链表怎么实战?——如何用一张表保留完整历史又不爆炸存储?』——建模题第三道,也是数仓里最经典的 SCD Type 2 方案。
你们的宽表有多少字段?有没有那种『加进去三年没人敢删』的遗产字段?
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长