4. 沙盘环境搭建:模拟风控数据仓库环境、数据表结构设计、模拟脏数据注入规则

沙盘推演的核心在于构建一个“真实但可控”的战场。本章将带领学员从零搭建一套模拟风控数据仓库环境,设计核心数据表结构,并制定一套标准化的脏数据注入规则。这套环境将作为后续所有推演战役的“数据沙盘”,确保每一次优化动作都有据可依、可量化、可复现。

4.1 模拟风控数据仓库环境架构

我们采用经典的“贴源层(ODS)→ 明细层(DWD)→ 汇总层(DWS)→ 应用层(ADS)”四层架构,并针对风控场景进行轻量化改造。环境基于 PostgreSQL 12+ 构建,所有脚本均兼容标准 SQL。

环境规格: 单节点部署,4 vCPU / 16 GB RAM,500 GB SSD。数据库名:risk_sandbox。Schema 命名规则:ods、dwd、dws、ads。
风控数据仓库四层架构图 风控数据仓库四层架构(沙盘环境) ODS 贴源层 ods.order_info, ods.user_profile, ods.payment_log DWD 明细层 dwd.order_detail_di, dwd.user_behavior_wide DWS 汇总层 dws.user_daily_agg, dws.merchant_risk_summary ADS 应用层 ads.risk_score_result, ads.rule_engine_output

4.2 核心数据表结构设计

我们聚焦风控最核心的三大实体:用户、订单、支付。每张表都预留了“质量监控字段”,用于后续推演中的数据质量探测。

4.2.1 用户画像表(ods.user_profile)

字段名类型约束说明
user_idVARCHAR(32)PK, NOT NULL用户唯一标识
user_nameVARCHAR(64)NOT NULL用户姓名
id_cardVARCHAR(18)—身份证号(模拟)
mobileVARCHAR(11)—手机号
emailVARCHAR(128)—电子邮箱
register_timeTIMESTAMPNOT NULL注册时间
user_levelVARCHAR(16)—用户等级(L0/L1/L2)
is_blacklistedBOOLEANDEFAULT FALSE是否黑名单
etl_timeTIMESTAMPDEFAULT NOW()数据注入时间

4.2.2 订单明细表(ods.order_info)

字段名类型约束说明
order_idVARCHAR(32)PK, NOT NULL订单唯一标识
user_idVARCHAR(32)FK, NOT NULL关联用户
merchant_idVARCHAR(32)NOT NULL商户ID
order_amountDECIMAL(12,2)NOT NULL订单金额
order_statusVARCHAR(16)—状态:PENDING/SUCCESS/FAILED
order_timeTIMESTAMPNOT NULL下单时间
ip_addressVARCHAR(45)—下单IP
device_fingerprintVARCHAR(128)—设备指纹
etl_timeTIMESTAMPDEFAULT NOW()数据注入时间

4.2.3 支付流水表(ods.payment_log)

字段名类型约束说明
payment_idVARCHAR(32)PK, NOT NULL支付流水号
order_idVARCHAR(32)FK, NOT NULL关联订单
payment_methodVARCHAR(16)—支付方式:WECHAT/ALIPAY/CARD
payment_amountDECIMAL(12,2)NOT NULL支付金额
payment_statusVARCHAR(16)—状态:SUCCESS/FAILED/REFUND
payment_timeTIMESTAMPNOT NULL支付时间
channel_feeDECIMAL(10,4)—渠道手续费
etl_timeTIMESTAMPDEFAULT NOW()数据注入时间

4.3 模拟脏数据注入规则

为了真实还原风控数据治理的痛点,我们设计了 6 大类、18 种 脏数据注入规则。这些规则将随机或按比例注入到上述三张核心表中,模拟生产环境中的常见数据质量问题。

推演提示: 脏数据注入比例建议控制在总数据量的 5% ~ 15% 之间,过低无法暴露问题,过高则脱离实际。沙盘默认注入比例为 8%。

4.3.1 脏数据分类与注入规则清单

类别规则编号注入描述目标字段注入方式
完整性缺失D01关键字段置 NULLuser_id, order_amountUPDATE SET = NULL
D02外键悬空(孤儿记录)order_info.user_id插入不存在的 user_id
D03必填字段空字符串user_name, order_statusUPDATE SET = ''
格式异常D04身份证号位数错误id_card替换为 15 位或 19 位数字
D05手机号含非法字符mobile插入 '138-0000-1111'
D06邮箱缺少 @ 符号email替换为 'user_at_example.com'
逻辑矛盾D07订单金额为负数order_amountUPDATE SET = -99.99
D08支付时间早于下单时间payment_timeSET = order_time - INTERVAL '1 day'
D09订单状态与支付状态冲突order_status订单 FAILED 但支付 SUCCESS
重复数据D10主键重复插入order_idINSERT 相同 order_id
D11业务含义重复(同人同订单)user_id + order_time完全相同的记录插入两次
D12部分字段重复device_fingerprint大量订单共享同一设备指纹
值域越界D13金额超出合理范围order_amountSET = 99999999.99
D14时间戳为未来时间register_timeSET = NOW() + INTERVAL '10 years'
D15枚举值不在定义域内user_level插入 'L99'
引用不一致D16汇总层与明细层金额不匹配dws.user_daily_agg汇总金额 ≠ 明细求和
D17跨表关联字段类型不一致user_idods 为 VARCHAR,dwd 误用 INT
D18编码不一致(GBK vs UTF8)merchant_id混入乱码字符

4.4 脏数据注入脚本示例

以下为规则 D01(关键字段置 NULL)和 D07(金额为负数)的 SQL 注入脚本,学员可直接在沙盘环境中执行。

-- 规则 D01:将 5% 的订单金额置为 NULL
UPDATE ods.order_info
SET order_amount = NULL
WHERE order_id IN (
    SELECT order_id FROM ods.order_info
    TABLESAMPLE BERNOULLI(5)
);

-- 规则 D07:将 3% 的订单金额改为负数
UPDATE ods.order_info
SET order_amount = -ABS(order_amount)
WHERE order_id IN (
    SELECT order_id FROM ods.order_info
    TABLESAMPLE BERNOULLI(3)
);

-- 规则 D10:主键重复插入(需先关闭主键约束或使用临时表)
INSERT INTO ods.order_info (order_id, user_id, merchant_id, order_amount, order_time)
SELECT order_id, user_id, merchant_id, order_amount, order_time
FROM ods.order_info
WHERE order_id IN (
    SELECT order_id FROM ods.order_info
    TABLESAMPLE BERNOULLI(2)
);
⚠️ 沙盘操作警告: 注入脏数据前,请务必执行 CREATE TABLE ods.order_info_bak AS SELECT * FROM ods.order_info; 备份原始数据。推演结束后,可通过 TRUNCATE 并重新导入备份来重置沙盘。

4.5 数据质量监控基线

在注入脏数据之前,我们需要建立一套“零污染”基线指标,用于对比脏数据注入后的质量偏差。基线指标将作为后续推演中“数据质量评分卡”的基准值。

数据质量基线指标示意 数据质量基线指标(注入前) 完整性 基线值:100% 准确性 基线值:100% 一致性 基线值:100% 时效性 基线值:100% 唯一性 基线值:100% 基线说明:注入脏数据前,所有质量维度均为 100%。 推演目标:通过治理手段,将各维度恢复至 ≥ 99.5%。

4.6 沙盘环境初始化步骤

  1. 创建数据库与 Schema: 执行 CREATE DATABASE risk_sandbox; 并依次创建 ods、dwd、dws、ads 四个 Schema。
  2. 执行建表脚本: 按 4.2 节结构创建三张核心表,并添加主键、外键及索引。
  3. 生成模拟数据: 使用 Python Faker 库或 pgAdmin 的数据生成工具,生成 10 万条用户、50 万条订单、80 万条支付流水。
  4. 备份基线数据: 执行 CREATE TABLE ... AS SELECT * 备份三张表的纯净版本。
  5. 执行脏数据注入: 按 4.3 节规则,随机选取 8% 的数据执行注入脚本。
  6. 验证注入效果: 运行数据质量探查 SQL,确认脏数据已成功注入且比例符合预期。