代理键与自然键

代理键是数仓生成的无业务含义整数键(自增或序列),用于事实表关联维度并支撑缓慢变化维的多版本;自然键(业务键)用于与源系统对齐、识别同一实体。

代理键与自然键是什么

代理键是数仓自己生成、唯一且无业务含义的整数键(自增、序列或哈希),事实表用它关联维度;自然键是源系统的业务主键(订单号、用户 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)而不是留空:空外键会让内连接静默丢行,指标偏低却查不出原因。

易错点

  • 事实表直接存业务键,SCD2 多版本时无法定位交易发生当时的维度版本
  • 给代理键赋予业务含义(把地区码编进 key),业务规则一变就要整体返工
  • 维度表只有代理键没有自然键,出问题时无法回溯到源单据做对账
  • 事实表关联不到维度就写 NULL,内连接查询静默丢行导致指标偏低
  • 用哈希键跨库统一却不做碰撞校验,极端情况下两个实体被合并成一条

数据来源与参考

  • Kimball《The Data Warehouse Toolkit》代理键(Surrogate Key)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌