Files

441 lines
18 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 设计文档DWD 业务全景梳理
## 概述
本设计文档描述如何系统梳理飞球 ETL 的 DWD 层全部业务数据,产出 5 份全景分析文档。这是一个纯文档梳理任务,不涉及代码改动,核心挑战在于:如何在"数据本源优先"的强制准则下,高效、准确地完成 7 个业务域、约 30 张表(含扩展表)的字段语义验证和跨表关联分析。
### 设计目标
1. 定义可重复执行的梳理方法论,确保每张表的分析过程一致
2. 设计每份文档的结构模板,确保产出物格式统一
3. 规划数据验证的技术方案,确保结论可追溯
4. 设计文档间的引用和关联机制,避免信息重复
### 范围
- 输入:`test_etl_feiqiu` 数据库 DWD schema 的全部表和数据
- 参考:现有 BD 手册(`apps/etl/connectors/feiqiu/docs/database/DWD/`)、已有分析报告(`docs/reports/`
- 产出5 份全景文档,输出到 `docs/reports/`
### DWD 表全景
根据现有 BD 手册DWD 层包含以下表:
| 类型 | 表数量 | 表名 |
|------|--------|------|
| 维度表(主表) | 9 | `dim_site`, `dim_table`, `dim_assistant`, `dim_member`, `dim_member_card_account`, `dim_tenant_goods`, `dim_store_goods`, `dim_goods_category`, `dim_groupbuy_package` |
| 维度表(扩展表) | 8 | 上述除 `dim_goods_category` 外均有 `_ex` 扩展表 |
| 事实表(主表) | 13 | `dwd_settlement_head`, `dwd_payment`, `dwd_table_fee_log`, `dwd_table_fee_adjust`, `dwd_assistant_service_log`, `dwd_member_balance_change`, `dwd_recharge_order`, `dwd_refund`, `dwd_groupbuy_redemption`, `dwd_platform_coupon_redemption`, `dwd_store_goods_sale`, `dwd_goods_stock_summary`, `dwd_goods_stock_movement` |
| 事实表(扩展表) | 11 | 除 `dwd_payment`, `dwd_goods_stock_summary`, `dwd_goods_stock_movement` 外均有 `_ex` 扩展表 |
共计约 43 张表。
## 架构
### 整体梳理流程
梳理工作分为两个阶段:基础层(表结构与字段语义)和全景层(跨表关联分析)。基础层产出为全景层的输入。
```mermaid
flowchart TD
subgraph Phase1["阶段一:基础层梳理"]
A[枚举 DWD 全部表] --> B[按业务域分组]
B --> C[逐表执行智能聚焦分析]
C --> D[字段分类筛选]
D --> E[业务关键字段倒推验证]
E --> F[产出DWD 表结构与字段语义总览]
end
subgraph Phase2["阶段二:全景层梳理"]
F --> G[业务全景:消费产生机制]
F --> H[账务全景:结算与支付]
F --> I[财务全景:收入与对账]
F --> J[维度表与主数据全景]
end
subgraph Validation["贯穿:数据验证"]
K[information_schema 查表结构]
L[SQL 查询验证值域分布]
M[交叉查询验证关联关系]
N[对账公式全量验证]
end
C -.-> K
E -.-> L
E -.-> M
H -.-> N
```
### 信息流向
```mermaid
flowchart LR
subgraph 输入源
DB[(test_etl_feiqiu<br/>DWD schema)]
BD[现有 BD 手册<br/>宏观参考]
RPT[已有分析报告<br/>待验证假设]
end
subgraph 梳理过程
DB -->|information_schema| META[表结构元数据]
DB -->|SQL 查询| DATA[实际数据验证]
BD -->|宏观层可参考| REF[参考起点]
RPT -->|字段级需验证| HYP[待验证假设]
end
subgraph 产出
META --> DOC1[文档1: 表结构总览]
DATA --> DOC1
REF --> DOC1
HYP --> DOC1
DOC1 --> DOC2[文档2: 业务全景]
DOC1 --> DOC3[文档3: 账务全景]
DOC1 --> DOC4[文档4: 财务全景]
DOC1 --> DOC5[文档5: 维度表全景]
end
```
## 组件与接口
### 组件一:单表智能聚焦分析器
对每张 DWD 表执行标准化的分析流程,产出该表的字段语义报告。
#### 分析流程(每张表)
```
步骤 1: 表结构获取
→ 查询 information_schema.columns 获取列名、类型、nullable
→ 禁止参考 db/ 目录下的 DDL .sql 文件
步骤 2: 字段分类筛选
→ 查询全表空字段SELECT column WHERE ALL NULL标记为"空字段-跳过"
→ 识别 ETL 管理字段_etl_loaded_at, _etl_batch_id 等),简要标注
→ 识别含义透明字段id, site_id, created_at 等),仅列出
→ 剩余为"业务关键字段",进入深度验证
步骤 3: 业务关键字段倒推验证
→ 从含义明确的字段出发(如 id, site_id, total_amount
→ 通过 JOIN / 聚合对比 / 值域交叉推断不确定字段
→ 金额字段MIN/MAX/AVG/中位数/NULL占比 + 交叉验证
→ 枚举字段DISTINCT 值 + 频次分布
→ 关联 IDJOIN 验证关联完整性
步骤 4: 偏差检测
→ 对比现有 BD 手册的字段描述
→ 标注一致/偏差/错误
```
#### 输出格式(每张表)
```markdown
### {table_name}
**业务职责**:一句话描述
**数据状态**{行数} 行,时间范围 {min_date} ~ {max_date}
**主键**{pk_fields}
**关联表**{related_tables with join fields}
#### 业务关键字段
| 字段名 | 类型 | 验证状态 | 语义说明 | 值域/分布 |
|--------|------|----------|----------|-----------|
| ... | ... | ✅/⚠️/❌ | ... | ... |
#### 空字段(附录)
{列出全 NULL 的字段名}
#### 偏差记录
{与现有文档不一致的地方}
```
### 组件二:全景文档生成器
基于单表分析结果,按业务视角组织跨表关联分析。
#### 全景文档通用模板
```markdown
# {全景文档标题}
> 数据来源test_etl_feiqiu (DWD schema)
> 验证日期:{date}
> 数据时间范围:{min_date} ~ {max_date}
## 目录
{自动生成}
## 正文
{按业务逻辑组织的分析内容}
{每个关键结论标注验证状态:✅ 已验证 / ⚠️ 部分验证 / ❌ 未验证}
## 附录
### 验证 SQL
{关键验证查询}
### 数据样例
{来自测试库的真实数据}
```
### 组件三:数据验证引擎
贯穿整个梳理过程的验证机制。
#### 验证类型
| 验证类型 | 方法 | 适用场景 |
|----------|------|----------|
| 值域验证 | MIN/MAX/AVG/MEDIAN/NULL% | 金额字段、数值字段 |
| 枚举验证 | DISTINCT + COUNT | 状态字段、类型字段 |
| 关联验证 | LEFT JOIN + NULL 检查 | 外键关联完整性 |
| 等式验证 | SUM 对比 | 对账公式F1~F6 等) |
| 交叉验证 | 多表 JOIN + 聚合对比 | 跨表金额一致性 |
| 边界验证 | WHERE = 0 / < 0 / IS NULL | 异常值业务含义 |
#### 验证结果标注规范
- ✅ 已验证:附验证 SQL 摘要或结果统计
- ⚠️ 部分验证:附已知例外数量和分类
- ❌ 未验证:附原因(数据不足/无法关联/逻辑不明)
- ⚠️ 警告:经多次交叉验证仍无法对齐的数据关系
## 数据模型
### DWD 表按业务域分组
本次梳理将 DWD 层全部表按 7 个业务域组织,每个域内的表构成一个分析单元。
```mermaid
erDiagram
%% 结算域
dwd_settlement_head ||--o{ dwd_payment : "order_settle_id"
dwd_settlement_head ||--o{ dwd_table_fee_log : "order_settle_id"
dwd_settlement_head ||--o{ dwd_store_goods_sale : "order_settle_id"
dwd_settlement_head ||--o{ dwd_assistant_service_log : "order_settle_id"
dwd_settlement_head ||--o{ dwd_platform_coupon_redemption : "order_settle_id"
dwd_settlement_head ||--o{ dwd_refund : "order_settle_id"
%% 台桌域
dim_table ||--o{ dwd_table_fee_log : "table_id"
dwd_table_fee_log ||--o{ dwd_table_fee_adjust : "table_fee_log_id"
%% 助教域(作废判断已内聚到 dwd_assistant_service_log_ex.is_trash
dim_assistant ||--o{ dwd_assistant_service_log : "assistant_id"
%% 会员域
dim_member ||--o{ dim_member_card_account : "member_id"
dim_member ||--o{ dwd_member_balance_change : "member_id"
dim_member_card_account ||--o{ dwd_recharge_order : "tenant_member_card_id"
%% 团购域
dim_groupbuy_package ||--o{ dwd_groupbuy_redemption : "groupbuy_package_id"
%% 商品域
dim_goods_category ||--o{ dim_tenant_goods : "category_id"
dim_tenant_goods ||--o{ dim_store_goods : "tenant_goods_id"
dim_store_goods ||--o{ dwd_store_goods_sale : "site_goods_id"
dim_store_goods ||--o{ dwd_goods_stock_summary : "site_goods_id"
dim_store_goods ||--o{ dwd_goods_stock_movement : "site_goods_id"
%% 门店维度
dim_site ||--o{ dwd_settlement_head : "site_id"
```
### 业务域与表映射
| 业务域 | 事实表 | 维度表 | 核心关联 |
|--------|--------|--------|----------|
| 结算 | `dwd_settlement_head`(+ex), `dwd_payment`, `dwd_refund`(+ex) | — | 结算单是所有消费的汇总入口 |
| 台桌 | `dwd_table_fee_log`(+ex), `dwd_table_fee_adjust`(+ex) | `dim_table`(+ex) | 台费计费流水 → 台费调整 |
| 助教 | `dwd_assistant_service_log`(+ex) | `dim_assistant`(+ex) | 助教服务流水(作废通过 `_ex.is_trash` 判断) |
| 会员 | `dwd_member_balance_change`(+ex), `dwd_recharge_order`(+ex) | `dim_member`(+ex), `dim_member_card_account`(+ex) | 充值 → 余额变动 |
| 团购 | `dwd_groupbuy_redemption`(+ex), `dwd_platform_coupon_redemption`(+ex) | `dim_groupbuy_package`(+ex) | 团购核销 → 平台券核销 |
| 商品 | `dwd_store_goods_sale`(+ex) | `dim_tenant_goods`(+ex), `dim_store_goods`(+ex), `dim_goods_category` | 商品销售流水 |
| 库存 | `dwd_goods_stock_summary`, `dwd_goods_stock_movement` | (复用商品域维度表) | 库存汇总 + 变动流水 |
### 5 份文档的数据依赖关系
```mermaid
flowchart TD
DOC1["文档1: DWD 表结构与字段语义总览<br/>覆盖全部 43 张表"]
DOC1 --> DOC2["文档2: 业务全景<br/>消费产生机制"]
DOC1 --> DOC3["文档3: 账务全景<br/>结算与支付流水"]
DOC1 --> DOC4["文档4: 财务全景<br/>收入确认与对账"]
DOC1 --> DOC5["文档5: 维度表与主数据全景<br/>全部维度表"]
DOC2 -->|消费构成| DOC3
DOC2 -->|消费金额| DOC4
DOC3 -->|支付渠道| DOC4
DOC5 -->|维度关联| DOC2
DOC5 -->|维度关联| DOC3
```
### 文档产出路径与文件名
| 序号 | 文档 | 文件名 | 路径 |
|------|------|--------|------|
| 1 | DWD 表结构与字段语义总览 | `dwd-table-structure-overview.md` | `docs/reports/` |
| 2 | 业务全景:消费产生机制 | `dwd-business-panorama.md` | `docs/reports/` |
| 3 | 账务全景:结算与支付流水 | `dwd-accounting-panorama.md` | `docs/reports/` |
| 4 | 财务全景:收入确认与对账 | `dwd-financial-panorama.md` | `docs/reports/` |
| 5 | 维度表与主数据全景 | `dwd-dimension-panorama.md` | `docs/reports/` |
### 文档间引用规范
- 文档间使用相对路径引用:`[表结构总览](./dwd-table-structure-overview.md#table_name)`
- 引用已有分析报告:`[消费金额口径分析](./consume-money-caliber-deep-analysis.md#章节名)`
- 引用 BD 手册:`[BD 手册](../../apps/etl/connectors/feiqiu/docs/database/DWD/main/BD_manual_xxx.md)`
- 引用结论时标注验证状态和来源文档
## 正确性属性
*属性Property是一种在系统所有合法执行中都应成立的特征或行为——本质上是对系统应做什么的形式化陈述。属性是人类可读规格与机器可验证正确性保证之间的桥梁。*
### Property 1: DWD 表覆盖完整性
*对于* DWD schema`test_etl_feiqiu.dwd`)中 `information_schema.tables` 返回的任意表,产出的文档集合中必须包含对该表的描述段落(表名出现在某份文档的标题或表格中)。
**Validates: Requirements 1.1, 5.1**
### Property 2: 主键标注准确性
*对于* DWD schema 中的任意表,文档中记录的主键字段集合必须与 `information_schema.table_constraints` + `key_column_usage` 查询返回的实际主键约束一致。
**Validates: Requirements 1.5**
### Property 3: 业务环节数据佐证
*对于* 业务全景文档文档2中描述的任意业务环节段落该段落必须包含至少一个来自测试库的数据样例以代码块或表格形式呈现的查询结果
**Validates: Requirements 2.6**
### Property 4: 对账公式验证一致性
*对于* 账务全景文档文档3中列出的任意对账公式文档中标注的成立率和例外数量必须与在 `test_etl_feiqiu` 全量数据上执行该公式验证 SQL 的实际结果一致。
**Validates: Requirements 3.5, 6.2**
### Property 5: 文档元数据完整性
*对于* 产出的任意全景文档,文档开头必须包含:(a) 数据来源标注(`test_etl_feiqiu`)、(b) 验证日期、(c) 数据时间范围(最早和最晚记录的时间)。
**Validates: Requirements 6.4**
### Property 6: 文档输出路径正确性
*对于* 本次梳理产出的任意文档文件,其路径必须位于 `docs/reports/` 目录下。
**Validates: Requirements 7.1**
### Property 7: 文档模板一致性
*对于* 产出的任意全景文档,其结构必须包含以下模板元素:标题、数据来源与验证日期块、目录、正文、附录(含验证 SQL 或数据样例)。
**Validates: Requirements 7.3**
### Property 8: 内部链接格式
*对于* 产出文档中的任意内部链接(指向本项目其他 markdown 文件的链接),链接必须使用相对路径格式(以 `./``../` 开头),且目标文件实际存在。
**Validates: Requirements 7.5**
## 错误处理
本任务是纯文档梳理,不涉及运行时代码。"错误"主要指梳理过程中遇到的数据异常和验证失败。
### 数据异常处理策略
| 异常场景 | 处理方式 | 文档标注 |
|----------|----------|----------|
| 表无数据0 行) | 跳过字段语义验证,仅记录表结构 | `❌ 未验证:表无数据` |
| 数据量不足(<10 行) | 执行有限验证,标注样本量不足 | `⚠️ 部分验证:仅 N 行数据` |
| 字段全 NULL | 标记为空字段,不展开分析 | 附录中列出字段名 |
| 对账公式不成立 | 分析例外案例,量化影响范围 | `⚠️ 成立率 X%,例外 N 笔` |
| 交叉验证矛盾 | 记录矛盾细节,标注为不确定 | `⚠️ 警告:无法对齐` |
| 现有文档与数据不一致 | 以数据为准,记录偏差 | `偏差记录` 段落 |
### 不确定性升级机制
当遇到以下情况时,必须在文档中以 `⚠️ 警告` 醒目标记:
1. 经过 ≥3 次不同角度的交叉验证仍无法确认的字段含义
2. 对账公式成立率 < 95% 且无法归因的例外
3. 金额字段的计算关系无法通过任何已知公式解释
4. 枚举值在现有文档中未记录且无法通过数据推断含义
警告内容须包含:已尝试的验证方法、无法确认的具体原因、建议的后续验证方向。
## 测试策略
### 测试方法说明
本任务的产出物是 markdown 文档而非代码,因此传统的单元测试和属性测试需要适配为"文档正确性验证"。
### 属性测试Property-Based Testing
使用 Python + `hypothesis` 库,针对设计文档中定义的正确性属性编写验证脚本。
**测试库**`hypothesis`(项目已有,见 `tests/` 目录)
**最低迭代次数**100 次(对于涉及随机采样的属性)
**测试位置**`tests/` 目录Monorepo 级属性测试)
#### 属性测试实现方案
| Property | 测试方法 | 实现思路 |
|----------|----------|----------|
| P1: 表覆盖完整性 | 查询 information_schema → 解析文档 → 比对 | 从数据库获取全部 DWD 表名,解析 5 份文档提取提及的表名,验证覆盖率 = 100% |
| P2: 主键标注准确性 | 查询 PK 约束 → 解析文档 → 比对 | 对于随机采样的 N 张表,比对文档中的主键与数据库实际主键 |
| P3: 业务环节数据佐证 | 解析文档段落 → 检查数据样例 | 解析业务全景文档的每个业务环节段落,验证包含代码块或数据表格 |
| P4: 对账公式验证一致性 | 提取公式 → 执行 SQL → 比对成立率 | 对于文档中的每个对账公式,重新执行验证 SQL比对成立率 |
| P5: 文档元数据完整性 | 解析文档头部 → 检查必要字段 | 对于每份文档,检查开头是否包含数据来源、验证日期、时间范围 |
| P6: 文档路径正确性 | 列出产出文件 → 检查路径 | 验证所有产出文件位于 `docs/reports/` |
| P7: 文档模板一致性 | 解析文档结构 → 检查模板元素 | 对于每份文档,检查是否包含标题、元数据块、目录、正文、附录 |
| P8: 内部链接格式 | 正则提取链接 → 检查格式和目标 | 提取所有 markdown 链接,验证使用相对路径且目标文件存在 |
#### 属性测试标签格式
每个属性测试必须包含注释标签:
```python
# Feature: dwd-business-panorama, Property 1: DWD 表覆盖完整性
# Feature: dwd-business-panorama, Property 2: 主键标注准确性
# ...
```
### 单元测试(示例测试)
针对 prework 中标记为 `yes - example` 的验收标准:
| 验收标准 | 测试内容 |
|----------|----------|
| 1.6 SCD2 字段标注 | 检查 `dim_member` 文档中是否标注了 `scd2_start_time`, `scd2_end_time`, `scd2_is_current`, `scd2_version` |
| 2.2 消费类目覆盖 | 检查业务全景文档中是否包含"台费"、"商品消费"、"助教服务"、"灯控电费"四个关键词 |
| 2.5 团购三层价格 | 检查文档中是否提及 `sale_price``pl_coupon_sale_amount``coupon_amount` |
| 2.7 Mermaid 流程图 | 检查业务全景文档中是否包含 ` ```mermaid` 代码块 |
| 3.7 consume_money 三种口径 | 检查文档中是否包含口径 A、B、C 的描述 |
| 4.5 对账矩阵 | 检查财务全景文档中是否包含矩阵格式的表格 |
| 7.2 5 份文档产出 | 检查 `docs/reports/` 下是否存在 5 个指定文件名 |
| 7.4 Mermaid 图表 | 检查每份文档中是否包含至少一个 Mermaid 代码块 |
### 边界条件测试
| 验收标准 | 边界场景 |
|----------|----------|
| 1.7 表无数据 | 验证无数据表在文档中有"数据不足"标注 |
### 测试执行
```bash
# 属性测试Monorepo 级)
cd C:\NeoZQYY && pytest tests/test_dwd_panorama_properties.py -v
# 单元测试
cd C:\NeoZQYY && pytest tests/test_dwd_panorama_examples.py -v
```