init: 项目初始提交 - NeoZQYY Monorepo 完整代码
This commit is contained in:
180
apps/etl/pipelines/feiqiu/docs/business-rules/scd2_rules.md
Normal file
180
apps/etl/pipelines/feiqiu/docs/business-rules/scd2_rules.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# SCD2 缓慢变化维处理规则
|
||||
|
||||
本文档定义 `billiards_dwd` 模式下维度表的 SCD2(Slowly Changing Dimension Type 2)处理策略、
|
||||
生效区间管理和版本控制规则。
|
||||
|
||||
> **状态**:骨架文档,各维度表的跟踪字段与变更触发条件待补充。
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
### 1.1 什么是 SCD2
|
||||
|
||||
SCD2 通过保留维度记录的历史版本来追踪属性变化。当被跟踪字段发生变更时:
|
||||
1. 关闭当前版本(设置结束时间、标记为非当前)
|
||||
2. 插入新版本(设置开始时间、标记为当前)
|
||||
|
||||
### 1.2 实现模块
|
||||
|
||||
- 处理器:`scd/scd2_handler.py` — `SCD2Handler` 类
|
||||
- 核心方法:`upsert(table_name, natural_key, tracked_fields, record, effective_date)`
|
||||
- 返回值:`INSERT`(新记录)、`UPDATE`(属性变更)、`UNCHANGED`(无变化)
|
||||
|
||||
---
|
||||
|
||||
## 2. SCD2 元数据字段
|
||||
|
||||
所有维度表统一包含以下 SCD2 控制字段:
|
||||
|
||||
| 字段 | 类型 | 默认值 | 说明 |
|
||||
|------|------|--------|------|
|
||||
| `scd2_start_time` | `TIMESTAMPTZ` | `now()` | 版本生效起始时间 |
|
||||
| `scd2_end_time` | `TIMESTAMPTZ` | `'9999-12-31'` | 版本失效时间(`9999-12-31` 表示当前有效) |
|
||||
| `scd2_is_current` | `INT` | `1` | 当前版本标记(`1` = 当前,`0` = 历史) |
|
||||
| `scd2_version` | `INT` | `1` | 版本号(自增) |
|
||||
|
||||
### 约束
|
||||
|
||||
- 主键:`(natural_key, scd2_start_time)` — 同一自然键的不同版本通过生效时间区分
|
||||
- 唯一索引:`WHERE scd2_is_current = 1` — 保证每个自然键只有一条当前记录
|
||||
- 排他约束(GiST):`tstzrange(scd2_start_time, scd2_end_time)` — 防止同一自然键的版本时间段重叠
|
||||
|
||||
---
|
||||
|
||||
## 3. 处理流程
|
||||
|
||||
```
|
||||
收到维度记录
|
||||
│
|
||||
▼
|
||||
按 natural_key 查找 valid_to IS NULL 的当前记录
|
||||
│
|
||||
├── 不存在 → INSERT 新记录(is_current=1, valid_from=now)
|
||||
│
|
||||
└── 存在 → 比较 tracked_fields
|
||||
│
|
||||
├── 无变化 → UNCHANGED(跳过)
|
||||
│
|
||||
└── 有变化 → UPDATE 旧记录(valid_to=now, is_current=0)
|
||||
INSERT 新记录(valid_from=now, is_current=1)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 维度表 SCD2 配置
|
||||
|
||||
### 4.1 门店维度(dim_site / dim_site_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`billiards_dwd`
|
||||
- 自然键:`site_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
|
||||
### 4.2 台桌维度(dim_table / dim_table_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`billiards_dwd`
|
||||
- 自然键:`table_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
|
||||
### 4.3 助教维度(dim_assistant / dim_assistant_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`billiards_dwd`
|
||||
- 自然键:`assistant_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
|
||||
### 4.4 会员维度(dim_member / dim_member_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`billiards_dwd`
|
||||
- 自然键:`member_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
|
||||
### 4.5 会员卡账户维度(dim_member_card_account / dim_member_card_account_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`billiards_dwd`
|
||||
- 自然键:`member_card_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
|
||||
### 4.6 商品维度(dim_tenant_goods / dim_tenant_goods_ex / dim_store_goods / dim_store_goods_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`billiards_dwd`
|
||||
- 自然键:`tenant_goods_id` / `site_goods_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
|
||||
### 4.7 商品分类维度(dim_goods_category)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`billiards_dwd`
|
||||
- 自然键:`category_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
|
||||
### 4.8 团购套餐维度(dim_groupbuy_package / dim_groupbuy_package_ex)
|
||||
|
||||
<!-- 待补充:自然键、跟踪字段列表 -->
|
||||
|
||||
- Schema:`billiards_dwd`
|
||||
- 自然键:`groupbuy_package_id`
|
||||
- 跟踪字段:*(待定义)*
|
||||
- 变更触发场景:*(待补充)*
|
||||
|
||||
---
|
||||
|
||||
## 5. 查询约定
|
||||
|
||||
### 获取当前有效记录
|
||||
|
||||
```sql
|
||||
SELECT * FROM billiards_dwd.dim_member
|
||||
WHERE scd2_is_current = 1;
|
||||
```
|
||||
|
||||
### 获取某时间点的历史快照
|
||||
|
||||
```sql
|
||||
SELECT * FROM billiards_dwd.dim_member
|
||||
WHERE scd2_start_time <= '2025-06-01'
|
||||
AND scd2_end_time > '2025-06-01';
|
||||
```
|
||||
|
||||
### 获取某记录的完整变更历史
|
||||
|
||||
```sql
|
||||
SELECT * FROM billiards_dwd.dim_member
|
||||
WHERE member_id = 12345
|
||||
ORDER BY scd2_start_time;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 注意事项
|
||||
|
||||
- **时区**:`scd2_start_time` / `scd2_end_time` 使用 `TIMESTAMPTZ`,统一以服务器时区存储
|
||||
- **并发安全**:当前实现在单次 ETL 运行内串行处理,未做行级锁;并发写入需额外保护
|
||||
- **删除策略**:维度记录不做物理删除,仅通过关闭版本(`scd2_is_current = 0`)标记失效
|
||||
|
||||
---
|
||||
|
||||
## 维护约定
|
||||
|
||||
- 新增维度表时,须在本文档添加对应章节
|
||||
- 跟踪字段变更时,须同步更新文档并评估历史数据影响
|
||||
- 文档统一 UTF-8 编码,中文撰写
|
||||
Reference in New Issue
Block a user