首页/数据/数仓建模速查/代理键设计 Surrogate Key
建模基础69 条

代理键设计 Surrogate Key

维度表用无业务含义的自增/序列代理键做主键,事实表存代理键关联;代理键隔离业务键变化,支持同一业务键多个版本。

数仓建模速查数据更新于 2026-10-13

代理键解决什么问题

代理键是维度表里由系统生成、不含业务含义的主键(自增、序列或哈希)。事实表存代理键而不是业务键,好处有两个:业务键变更时不会断链,以及同一业务键可以存在多个历史版本(SCD 类型的必要条件)。

基本信息

生成方式自增列、数据库序列,或对业务键计算哈希
维表侧代理键作为主键,业务键作为普通列保留
事实侧存代理键做关联,便于处理多版本维度
优点隔离业务键变化,支持历史版本,加载可并行
注意代理键与业务键的映射必须可回溯

典型使用场景

  • SCD 类型 2 维度:同一业务键多个版本,必须用代理键区分
  • 业务键会变:源系统重新编码或合并实体时,事实侧关联不受影响
  • 多源合并:同一实体在多个系统标识不同,统一后分配同一个代理键
  • 并行加载:用哈希生成减少序列单点依赖,提升加载吞吐
  • 维度属性变更审计:通过代理键定位具体命中哪个版本

维表与事实表

维表与事实表
-- 维度表:代理键做主键,业务键仅作普通列保留
-- dim_product(product_sk BIGINT, product_id STRING, name STRING, ...)

-- 事实表:存代理键,不存业务键
-- fact_order(order_id STRING, product_sk BIGINT, pay_amt DECIMAL(18,2))

-- 查询时通过代理键关联到具体维度版本
SELECT p.name, sum(f.pay_amt)
FROM fact_order f
JOIN dim_product p ON f.product_sk = p.product_sk   -- 用代理键关联
GROUP BY p.name;

-- 出现问题时用业务键回查代理键映射,定位到具体版本
-- SELECT product_sk, product_id FROM dim_product WHERE product_id = 'P1001';

代理键生成方式对比

方式优点代价
数据库自增实现简单,局部唯一并行写入易冲突,跨库不可直接合并
序列集中分配,顺序可控依赖单点,高并发下有等待
业务键哈希无单点、可并行、跨库稳定存在碰撞可能,需确认算法与冲突处理
代理键必须与业务键保持可回溯的映射关系并保留在维度表中。否则排查数据问题时只能看到一串无意义数字,无法判断事实行到底指向哪个实体。
用业务键哈希作为代理键时,算法与输入规范化规则要在全仓统一。大小写、前后空格、拼接来源标识处理不一致,会让同一实体产生两个不同代理键,维度表出现重复成员。

易错点

  • 事实表直接存业务键做关联,业务键一变更历史事实全部断链,需要在事实侧大范围修补
  • 代理键依赖单点自增序列,多任务并行加载时键冲突,加载批量失败
  • 维表未保留业务键列,出现数据问题时无法把代理键还原成业务实体
  • 哈希代理键算法不统一,同一实体算出两个键,维度重复且事实被拆到两个实体上

数据来源与参考

  • Kimball 方法论:代理键
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌