事实表中的 NULL 外键怎么处理?
面试怎么回答
事实已经发生时不能因维度缺失而丢掉。我通常在维度表预建 Unknown、Not Applicable、Invalid 等保留成员,事实表写对应代理键,而不是裸 NULL。真实维度迟到后,再按自然键幂等回填正式代理键。同时统一全仓保留键规范,并监控未知事实的数量、金额占比和未修复时长。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
订单已经产生,但商品维度还没同步过来。事实表的 product_key 是留 NULL,写 0,还是直接丢掉这条事实?
这看似是字段取值问题,实际上关系到事实完整性、维度迟到、指标口径和后续修复能力。
事实不能因为维度暂时缺失而丢失;用可解释的未知成员代理键承接事实,并区分未知、不适用、错误等原因,后续再做确定性回填。
不要直接丢事实
交易、点击或结算事实已经发生,维度关联失败不代表业务事件无效。若因为维度缺失就过滤事实,GMV、订单数等核心指标会被低估,而且事后很难知道丢了哪些数据。
裸 NULL 会破坏分析一致性
SQL Join 中 NULL 不等于任何值,普通内连接会把这些事实排除;GROUP BY 虽能聚成 NULL 组,但不同报表可能各自解释。更常见的建模方式是在维度中预建 Unknown Member,并在事实表写入对应代理键。
一个未知成员往往还不够
至少要区分“未知但未来可能补齐”“业务上不适用”“源系统值非法”“权限脱敏不可见”等情况。它们的处理责任和指标解释不同。可以用多个保留代理键,或增加 reason_code,避免所有异常都落成一个 0。

迟到维度需要可回填
当真实维度到达后,系统应能按业务自然键找到待修复事实,将 Unknown Key 更新为正式代理键。回填要固定范围、幂等执行,并记录修复数量;若事实表不可更新,则需要通过查询视图或后续快照层补偿。
代理键约定要全仓一致
不同主题若分别用 0、-1、999999 表示未知,会让跨域 Join 和指标治理失控。应该在数仓规范中统一保留键、名称、含义与是否参与指标,并让所有一致性维度都具备这些成员。
质量监控关注比例和时长
Unknown 并不等于可以长期忽略。应监控各原因的事实数量、金额占比、最老未修复时间和来源系统,超过阈值要定位是维度调度延迟、自然键映射失败还是源端脏数据。
参考资料
- 本文按维度建模与企业数据治理实践整理。