使用历史数据
1)任命和原则
目的:保存和处理过去的状态,使报告、模型和调查能够复制、准确和兼容。
原则:- 设计时间奖励:显式模式和查询中的时间模型。
- 可重复性:相同的D日期报告始终产生相同的结果。
- Auditability:可证明的起源(线性),不可变层,WORM在需要的地方。
- Cost-aware:存档图层、压缩、冷库和易于理解的SLA。
- Privacy-by-设计:在回顾性操作和法律查询中管理PII。
2)时间模型
事件时间:实际事件的时间(投注、存款)。
处理时间:系统何时处理记录(可能不同)。
Bitemporal:用于追溯编辑的存储和处理时间。
Validity间隔:"valid_from","valid_to","is_current"。
Queries:数据样本"如你所知T"。
sql event_time TIMESTAMP, -- event time processed_at TIMESTAMP, -- TIMESTAMP valid_from processing time, -- start of version validity valid_to TIMESTAMP, -- end of validity (NULL if current)
is_current BOOLEAN
3)存储层和格式
湖屋:青铜(raw append-only)→银(clean/SCD/正常化)→黄金(店面)。
ACID-форматы: Delta/Iceberg/Hudi (MERGE/Upsert, time-travel, snapshots).
Tiered storage: hot/warm/cold+WORM用于调节工件。
参与:"event_date","market","tenant";按频繁谓词(user/game/provider) 聚类/Z顺序。
4)测量历史化(SCD)
SCD I:重写-用于非关键编辑。
SCD II:完整历史;建议使用RG/KYC/流量通道/游戏属性。
SCD III:"之前/之后"是罕见的比较案例。
sql
MERGE INTO dim. users_scd t
USING stage. users u
ON t. user_pseudo_id = u. user_pseudo_id AND t. is_current = TRUE
WHEN MATCHED AND (t. rg_status <> u. rg_status OR t. country <> u. country) THEN
UPDATE SET is_current = FALSE, valid_to = CURRENT_TIMESTAMP
WHEN NOT MATCHED THEN
INSERT (user_pseudo_id, country, rg_status, valid_from, valid_to, is_current)
VALUES (u. user_pseudo_id, u. country, u. rg_status, CURRENT_TIMESTAMP, NULL, TRUE);
5)事实历史: 图片和bitemporal
快照(Snapshots):在白天/月底的集合快照(例如钱包余额)-加快历史报告的重新创建速度。
Bitemporal事实:记录事件时间和处理时间,以区分后期更正和回顾性计算。
Exactly once story: "event_id"+等效的MERGE。
6)时间旅行和可重复性
时间旅行:阅读"T时"表格以进行调试、事件和交换。
逻辑转换:变换工件(SQL/DBT版本,容器)和输出表中的"logic_version"标签。
Frozen outputs:黄金报告文物被捕获并且不被重写,hash和出口日志可用。
sql
SELECT
FROM silver. fact_bets VERSION AS OF 1678901234567
WHERE event_date = DATE '2025-10-31';
7) Backfill и Reprocessing
Backfill:初级/装载历史范围。
重新执行:修复错误或更改业务规则后重新计票。
- 相等性(MERGE/upsert),范围,配额,"暗运行"(dry-run)与度量比较。
- 我们将结果标记为:"recalc_reason","logic_version","reprocessed_at"。
1.Freeze当前的Gold;2)DLQ/DQ验证;3)Silver运行;4)比较度量;5)重新组装Gold;6)出版物和签名。
8)精度检查(重新计算)
校验和:与OLTP、PSP/提供商进行周转/数量核对。
两环验证:样本中的独立管道(A/B比较)。
公差:例如,GGR ≤ 0差异。每天2%。
sql
-- Duplicates
SELECT transaction_id, COUNT() c
FROM silver. payments
GROUP BY transaction_id
HAVING COUNT() > 1;
-- Unknown Currencies/Markets
SELECT p. currency
FROM silver. payments p
LEFT JOIN ref. currencies r ON r. code = p. currency
WHERE r. code IS NULL;
9)货币,时间,日历: 历史正确性
事件日期的FX:捕获"fx_rate_used"和"fx_source"。
本地市场时间:DST/时间区通过日历目录。
假期/季节性:单独的日历表,用于模型和报告。
sql
SELECT p. transaction_id,
p. amount_orig,
r. rate AS fx_rate_used,
p. amount_orig r. rate AS amount_base,
r. fx_source
FROM bronze. payment_events p
JOIN dim. fx_rates r
ON r. date = DATE(p. event_time) AND r. ccy_from = p. currency AND r. ccy_to = 'EUR';
10)PII,合规性和法律保留
PII最小化:别名,单独的安全映射。
DSAR/RTBF:可计算的投影和历史层的选择性编辑;合法保管义务的例外情况已经记录在桉。
Legal Hold:在范围/对象中删除"冻结"标志,用于报告工件的WORM。
审计:不变的出入和出口逻辑。
11)历史的DQ和lineage
DQ之类的代码(示例):yaml table: silver. fact_bets slo:
completeness_percent: 99. 5 freshness_minutes: 60 rules:
- name: unique_bet type: unique columns: [bet_id]
severity: critical
- name: market_known type: in_set column: market set_ref: ref. markets
- name: ts_in_range type: temporal expression: "event_time BETWEEN date_sub(now(), interval 5 year) AND now()"
线性:捕获输入/转换/输出版本;依赖图对于反义是必需的。
12)生产力和成本
参与:按日期/市场/特南特分列;如果经常使用过滤器,则通过"user_pseudo_id"/"game_id"激进聚类。
格式:Parquet+统计/压缩;常规VACUUM/OPTIMIZE。
实现:用于"昂贵"历史汇总的precompute;季度/年度报告的快照。
归档:将旧批次转换为冷存储(记录了SLA的恢复)。
采集:仅用于研究任务,不用于监管/财务。
13)ML的历史fichi
功能注册表:每个幻灯片都有公式,所有者,SLO, "model_version"。
在线/离线一致性:一个转换代码库,可复制性测试。
特征漂移:按时期划分的PSI/KS,历史分布的存储。
14)查询模式
As of(按日期):报告的可复制性。
Cohort分析:注册/首次存款队列,滚动窗口。
Slowly changing facts: корректные join’ы с SCD II (`event_time BETWEEN valid_from AND COALESCE(valid_to, '9999-12-31')`).
带有SCD II的join'a示例:sql
SELECT b. bet_id, u. rg_status
FROM silver. fact_bets b
JOIN dim. users_scd u
ON u. user_pseudo_id = b. user_pseudo_id
AND b. event_time >= u. valid_from
AND (u. valid_to IS NULL OR b. event_time < u. valid_to);
15)流程和RACI
R(响应):数据工程(模型/SCD/backfill),数据平台(ACID/归档),财务/合规性(对账/存储要求)。
A (Accountable): Head of Data/CDO.
C(咨询):法律/DPO(DSAR/RTBF/Legal Hold),SRE(成本/SLA),体系结构。
I (Informed): BI/产品/营销/运营。
16)实施路线图
MVP(3-5周):1.时间旅行的ACID表(Delta/Iceberg/Hudi)和基本分期付款。
2.用于关键测量的SCD II(用户/游戏/提供者)。
3.关键单元的每日快照(GGR Daily)。
4.DQ码为(uniqueness/in_set/temporal)+线图。
第二阶段(5-10周):- Bitemporal事实,即API/SQL模板,runbooks backfill/reprocessing。
- FX/日历/DST丰富,OLTP↔DWH/provaydery对账。
- 冷存储,报告包的WORM归档,法律保留。
- 完全自动化"replay&what-if",比较指标和回归的变量。
- 历史的fici和ML漂移控制,按存储成本排序。
- 标记和可重现报告的"原样"文档。
17)售前支票清单
- 表支持时间旅行;VACUUM/RETENTION策略是一致的。
- SCD II用于关键测量;join's测试。
- D/M上的关键单元快照可通过对账进行验证。
- DQ规则是活跃的;lineage显示逻辑的输入/输出和版本。
- DSAR/RTBF/Legal Hold在历史层上进行了测试。
- 已记录和验证冷库存档和恢复。
- 控制存储成本(成本/GB, cold份额,恢复SLA)。
18)经常出错以及如何避免出错
没有显式时间模型:添加事件/处理/validity。
"追溯"FX:始终是事件发生时的路线,存储"fx_source"。
使用SCD的不规则加入:使用有效性间隔而不是"is_current"。
变异金色店面:报告输出必须不可变(或转化)。
没有lineage/DQ:没有可证明性和检查点-从第一天开始输入。
非管理成本:禁用热批次、真空、转换为冷。
19)词汇表
As of Query是对"T时刻的样子"的数据查询。
Bitemporal-同时提交事件和处理时间。
Snapshot是期末状态/聚合的实例化快照。
时间旅行-阅读表格的历史版本。
WORM是不可更改的存储(Write Once Read Many)。
20)结果
处理历史数据不仅仅是"长期存储",而是时间学科:显式事件/处理/bitemporal,SCD和snapshots模型,可重复查询性,严格的对账和合规控制,可观察性和经济高效的存储体系结构。遵循此指南,您将获得一个强大的历史基础,用于报告,分析和ML,可对业务逻辑进行审核和更改。