2. 因子库基础:什么是因子库、因子库的常见结构与存储方式

在风控建模与监控体系中,因子库是存放所有衍生特征(即因子)的中央仓库。它不仅是模型训练的数据源头,也是 PSI 漂移巡查的直接扫描对象。理解因子库的结构与存储方式,是搭建自动化监控体系的第一步。

2.1 什么是因子库

因子库是一个结构化存储的集合,用于统一管理从原始数据加工而来的衍生变量。每个因子通常包含以下元数据与数据内容:

维度 说明 示例
因子名称 唯一标识符,用于模型与监控系统引用 loan_amt_ratio
业务含义 描述因子代表的业务逻辑 贷款金额与收入的比例
计算逻辑 SQL 或 Python 表达式,用于生成因子值 loan_amt / income
数据类型 连续型、离散型、布尔型等 float
时间戳 因子值的计算日期或批次时间 2025-03-01
版本号 因子逻辑变更的版本标记 v2.1
关键认知: 因子库 ≠ 原始数据仓库。原始数据经过清洗、聚合、衍生后才进入因子库;因子库是面向模型与监控的“半成品”层。

2.2 因子库的常见结构

根据业务场景与查询模式,因子库主要采用两种表结构:宽表与窄表。两种结构在存储效率、查询性能与维护成本上各有优劣。

2.2.1 宽表结构

宽表将每个因子作为一列,一行代表一个样本(如一个用户、一笔订单)在某个时间点的全部因子值。

-- 宽表示例:user_factor_wide
user_id  |  dt         |  loan_amt_ratio  |  age_group  |  income_level  |  credit_score
---------|------------|------------------|-------------|----------------|--------------
U001     | 2025-03-01 | 0.45             | 30-35       | high           | 720
U002     | 2025-03-01 | 0.62             | 25-30       | medium         | 680
U003     | 2025-03-01 | 0.33             | 35-40       | low            | 650
优点 缺点
查询单样本所有因子时速度极快(一次 IO) 新增因子需要修改表结构(加列),DDL 成本高
适合模型推理时的批量特征读取 因子数量过多时(如 500+ 列),存储膨胀,维护困难
直观易理解,非技术人员也能直接查看 空值稀疏时浪费大量存储空间

2.2.2 窄表结构

窄表将因子名与因子值作为键值对存储,一行只记录一个因子。通常使用“实体-属性-值”(EAV)模型。

-- 窄表示例:user_factor_narrow
user_id  |  dt         |  factor_name     |  factor_value
---------|------------|------------------|--------------
U001     | 2025-03-01 | loan_amt_ratio   | 0.45
U001     | 2025-03-01 | age_group        | 30-35
U001     | 2025-03-01 | income_level     | high
U002     | 2025-03-01 | loan_amt_ratio   | 0.62
U002     | 2025-03-01 | age_group        | 25-30
优点 缺点
新增因子无需改表结构,直接插入新行即可 查询单样本全部因子需要多次 JOIN 或行转列,性能较低
存储紧凑,空值不占物理空间 数据行数膨胀(因子数 × 样本数),索引压力大
适合因子频繁迭代、动态扩展的场景 对 BI 工具不友好,通常需要物化视图辅助
实践建议: 多数风控团队采用“宽表为主、窄表为辅”的策略。生产监控使用宽表做批量 PSI 计算;因子开发与版本管理使用窄表记录变更历史。

2.3 因子库的存储方式

因子库的物理存储通常依赖以下三种方式,选择依据是数据规模、查询延迟与成本预算:

  1. 关系型数据库(RDBMS):如 MySQL、PostgreSQL。适合因子数量少(< 200)、查询并发高的场景。宽表结构下,配合索引可达到毫秒级单行查询。
  2. 列式存储引擎:如 ClickHouse、Doris。适合宽表结构下的大批量因子扫描。PSI 监控需要按时间分区读取全量因子分布,列式存储的压缩与聚合性能远优于行存。
  3. 分布式文件系统 + 分区表:如 Hive / Iceberg 按日期分区存储。适合超大规模因子库(千亿行级别),配合 Parquet 格式可实现高压缩比,但查询延迟通常在秒级到分钟级。
避坑提醒: 不要将因子库直接建在 OLTP 业务库上。因子计算与监控查询会大量扫描数据,极易引发业务库锁竞争与性能抖动。因子库应独立部署,或使用只读副本。

2.4 因子库结构对比总览

下表从监控巡查的视角,对比宽表与窄表在 PSI 计算场景下的表现:

对比维度 宽表 窄表
PSI 批量计算速度 快(一次扫描获取所有因子分布) 慢(需按因子名过滤 + 多次聚合)
新增因子对监控的影响 需修改 ETL 与监控脚本(加列) 自动纳入,只需在监控配置中注册新因子名
历史回溯难度 低(列固定,直接 WHERE 时间范围) 高(需行转列,且因子名可能变更)
存储空间(含空值) 高(每列固定长度,空值占位) 低(无空值不占行)
推荐场景 稳定因子库 + 高频 PSI 巡查 动态因子库 + 低频全量校验
因子库结构对比与存储架构 宽表结构 user_id | dt | f1 | f2 | f3 | ... U001 | 03-01 | 0.45 | 30 | high | ... U002 | 03-01 | 0.62 | 25 | med | ... U003 | 03-01 | 0.33 | 35 | low | ... 每列 = 一个因子,每行 = 一个样本 窄表结构 user_id | dt | factor_name | value U001 | 03-01 | f1 | 0.45 U001 | 03-01 | f2 | 30 U002 | 03-01 | f1 | 0.62 每行 = 一个因子值,因子名是数据 RDBMS 列式引擎 分布式文件 💡 监控选型建议: 宽表 + 列式引擎(如 ClickHouse)是 PSI 日巡场景的黄金组合;窄表适合因子快速迭代期的版本追溯。

2.5 因子库与 PSI 监控的衔接

在后续章节中,我们将基于因子库的宽表结构,按以下流程执行 PSI 漂移巡查:

  1. 基准分布提取:从因子库宽表中,按时间窗口(如最近 30 天)提取每个因子的分箱分布。
  2. 当前分布提取:按巡查周期(如每日)提取最新批次数据的因子分布。
  3. PSI 计算:逐因子计算基准与当前的分布差异,输出 PSI 值。
  4. 告警与归因:PSI 超过阈值的因子进入告警列表,结合窄表的历史版本追溯逻辑变更。
核心结论: 因子库的结构设计直接决定了 PSI 监控的计算效率与维护成本。宽表适合“快照式”批量扫描,窄表适合“追溯式”版本管理。在实际工程中,两者通常并存,互为补充。