1. SCD 概念与背景
1.1 什么是缓慢变化维?
先问大家一个问题:你公司的「客户」维度表,今天和昨天一样吗?
大概率不一样。客户会换手机号、改收货地址、公司名称变更、甚至婚姻状态都会变。这些变化,就是维度属性的变化。
那什么叫「缓慢变化维」?说白了,就是维度表中的数据,变化频率不高,但确实在变。它不像销售订单那样每秒都在产生,也不像产品目录那样几年不变。它处于中间地带——今天改个地址,明天换个电话,后天升个会员等级。
我个人的定义更直白:SCD 就是处理「维度属性变了,但历史数据怎么对齐」的那套方法论。
举个例子。你去年统计华东区销售额,客户「张三」当时在上海。今年张三搬到了北京,你把他地址改了。那去年的报表里,张三的销售额算华东还是华北?
这个问题,就是 SCD 要解决的。
核心定义:缓慢变化维(Slowly Changing Dimension, SCD)是指在数据仓库中,维度属性随时间发生非频繁、非规律性变化时,如何保持历史数据一致性与可追溯性的一系列处理策略。
1.2 为什么需要处理 SCD?
不处理行不行?
行,但后果很严重。我在项目中遇到过真实案例:某电商公司做用户生命周期分析,发现去年复购率突然暴跌。查了半天,原来是用户等级字段被直接覆盖了——去年还是「黄金会员」的用户,今年全变成了「钻石会员」。历史报表全乱了。
这就是典型的直接覆盖陷阱。你改了一个字段,所有历史数据跟着「穿越」了。
处理 SCD 的必要性,我总结为三点:
- 历史报表准确性:去年的销售额不能因为今天的地址变更而改变归属地
- 趋势分析可信度:用户等级变化、产品分类调整,必须能回溯到变化发生的时间点
- 审计与合规要求:金融、医疗等行业,监管要求保留完整的历史变更记录
你想想看,如果老板问你:「去年华东区业绩为什么下滑?」你总不能说「因为客户搬家了」吧?
避坑指南:我曾经接手过一个项目,上游业务系统每天全量覆盖维度表。结果做年度同比分析时,去年有 30% 的客户「凭空消失」了——因为他们的信息被新数据覆盖了。记住:维度表不是缓存,不能随便覆盖。
1.3 SCD 在数据仓库中的位置
数据仓库的经典架构,大家应该都熟悉:
- ODS(操作数据存储):贴源层,跟业务系统长得一样
- DWD(明细数据层):清洗、去重、标准化后的明细数据
- DWS(汇总数据层):按主题汇总的宽表
- ADS(应用数据层):面向报表和应用的轻度汇总
那 SCD 处理发生在哪一层?
我个人习惯放在 DWD 层。原因很简单:ODS 层要保持跟源系统一致,不能动;DWS 层已经聚合了,改起来成本太高。DWD 层是「清洗加工」的地方,正好做维度处理。
具体来说,SCD 处理涉及两个核心组件:
| 组件 | 位置 | 职责 |
|---|---|---|
| 维度表 | DWD 层 | 存储维度属性,支持历史版本管理 |
| 事实表 | DWD 层 | 通过代理键关联维度表,记录业务事件 |
| ETL 处理逻辑 | DWD 层加工过程 | 检测变化、生成新版本、更新有效期 |
这里有个关键点:代理键。业务主键(比如客户ID)不能作为维度表的主键,因为同一个客户会有多个版本。我们需要一个自增的、无业务含义的代理键来区分不同版本。
下面这张图,展示了 SCD 在整个数据仓库架构中的位置:
从这张图可以看得很清楚:SCD 处理是 DWD 层的核心职责之一。ODS 层不动,DWS/ADS 层直接用处理好的结果。所以,维度建模的质量,很大程度上取决于 SCD 策略选得好不好。
1.4 什么时候不需要 SCD?
不是所有维度都需要 SCD。我个人的经验是,先问三个问题:
- 这个属性会变吗?——比如性别,基本不变;但年龄每年都在变,不过通常用出生日期代替
- 变了之后影响历史分析吗?——比如产品颜色变了,去年的销售数据需要按新颜色归类吗?
- 业务方接受哪种方式?——有些业务场景,直接覆盖是最简单的,只要业务方认可
举个例子。产品「重量」这个属性,如果只是内部参考,变了就覆盖,没人会追究。但如果是「产品分类」,变了之后所有历史报表都要重新归类,那就必须用 SCD。
我的建议:刚开始做数据仓库时,别一上来就搞 SCD Type 2。先跟业务方确认:「这个属性变了,历史数据要不要跟着变?」如果答案是「要」,再考虑用哪种 SCD 策略。否则,直接覆盖是最省事的。
1.5 本章小结
这一章我们聊了三个核心问题:
- 什么是 SCD:维度属性随时间变化,需要一套策略来保持历史一致性
- 为什么需要 SCD:不处理会导致历史报表失真、趋势分析不可信、审计不合规
- SCD 在数据仓库中的位置:DWD 层,通过代理键关联维度表和事实表