代理键与自然键是什么
代理键是数仓自己生成、唯一且无业务含义的整数键(自增、序列或哈希),事实表用它关联维度;自然键是源系统的业务主键(订单号、用户 ID),用于与源端对齐、识别同一实体。两者分工明确:代理键承担「当时的那个维度版本」,自然键承担「这是哪个实体」。这也是缓慢变化维能记录多版本的前提——同一用户的不同历史版本各有独立代理键,事实表指向交易发生时的那一版。
基本信息
| 代理键 | 数仓生成、唯一、无业务含义、不随源端变化 |
|---|---|
| 自然键 | 源系统业务主键,可能被业务改写或复用 |
| 生成方式 | 自增序列、单调递增 ID、哈希(跨库统一但需处理碰撞) |
| 分工 | 事实表存代理键,同时保留自然键用于追溯与对账 |
| 多版本支持 | SCD2 下同一自然键对应多条代理键记录 |
| 特殊成员 | 常用 0 或 -1 等代理键表示未知或不适用,避免事实表出现空外键 |
典型使用场景
- 缓慢变化维:用户改城市后保留历史版本,事实表仍指向当时版本
- 源端主键变更:业务系统换号规则时,数仓内部关系不被牵连
- 跨源整合:多个源系统的同类实体合并到一张维度表,需要统一键
- 事实表关联:事实表按代理键关联维度,避免业务键参与连接带来的性能与语义问题
- 对账追溯:用自然键回到源业务单据核对明细
两个键并存
两个键并存
-- 维度表:代理键唯一,自然键可重复(SCD2 多版本)
SELECT user_sk, -- 代理键:数仓生成
user_id, -- 自然键:源端业务主键
city, valid_from, valid_to, is_current
FROM dim_user
WHERE user_id = 10086
ORDER BY valid_from;
-- 事实表:存代理键,关联到当时生效的维度版本
SELECT f.order_id, f.user_sk, u.city, f.amount
FROM fact_order f
JOIN dim_user u ON f.user_sk = u.user_sk
WHERE f.dt = '2026-10-11';两种键的分工
| 对比项 | 代理键 | 自然键 |
|---|---|---|
| 含义 | 无业务含义的整数 | 业务主键(订单号、用户 ID) |
| 稳定性 | 数仓内部稳定,不随源端变化 | 源端可能改写或复用,存在风险 |
| 在事实表中的角色 | 关联维度,定位具体版本 | 追溯、对账、与源端对齐 |
| SCD2 表现 | 一个自然键对应多个代理键 | 同一自然键重复出现 |
| 生成成本 | 需序列或哈希生成与唯一性保障 | 无需生成,直接来自源端 |
跨库联合建模时哈希键便于统一命名,但要处理碰撞与顺序性问题;多数场景自增序列更直观,也便于人工排查。
事实表关联不到维度时应落到未知成员(0 或 -1)而不是留空:空外键会让内连接静默丢行,指标偏低却查不出原因。