|
@@ -0,0 +1,202 @@
|
|
|
|
|
+# TDM 建模
|
|
|
|
|
+
|
|
|
|
|
+> 本数仓 TDM 层(主题域模型 / 画像层)的字段建模与设计约定。建模方法论见 `20-数仓分层与建模.md` §5;标签体系总览见 `23-标签体系.md`;命名规则见 `21-命名规范.md`;时间语义见 `26-时间语义.md`。
|
|
|
|
|
+>
|
|
|
|
|
+> 本文档按"表一节"组织,每节包含表用途 / 粒度 / 来源 / tag_code 清单 / 写入策略。
|
|
|
|
|
+
|
|
|
|
|
+## 1. 通用约定
|
|
|
|
|
+
|
|
|
|
|
+### 1.1 框架字段
|
|
|
|
|
+
|
|
|
|
|
+所有 TDM 表必带 `etl_time TIMESTAMP` + 分区 `dt STRING`,`STORED AS ORC`。
|
|
|
|
|
+
|
|
|
|
|
+### 1.2 EAV 长表 schema(kb/23 §2 严守 7 字段)
|
|
|
|
|
+
|
|
|
|
|
+所有标签表共用 EAV 7 字段,**不扩展**:
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 类型 | 说明 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| entity_id | BIGINT | 实体 id(用户场景 = user_id)|
|
|
|
|
|
+| tag_code | STRING | 标签编码(维度全 encode 到此字段,命名约定见 §4)|
|
|
|
|
|
+| tag_value | STRING | 标签值(统一 STRING;数值标签如 `"1500.00"`,下游 CAST 处理)|
|
|
|
|
|
+| tag_type | STRING | `attr` / `stat` / `rule`(预留枚举值 `algo` 给机器学习标签)|
|
|
|
|
|
+| confidence | DECIMAL(5,4) | 置信度(规则标签 1.0;模型标签按模型输出)|
|
|
|
|
|
+| etl_time | TIMESTAMP | ETL 处理时间 |
|
|
|
|
|
+| dt | STRING | 分区,按表语义取(见各表节)|
|
|
|
|
|
+
|
|
|
|
|
+**收益**:schema 不绑定标签维度组合;新增维度(如 channel / device 等)只需新 tag_code 命名,**不需 ALTER**。
|
|
|
|
|
+
|
|
|
|
|
+**代价**:维度切片需 `tag_code LIKE 'usr_pref_trade_%_amt_30d'` 模式匹配;数值标签聚合 / 排序需 `CAST(tag_value AS DECIMAL)`。
|
|
|
|
|
+
|
|
|
|
|
+### 1.3 表分类:_d 日更 / _o 一次性凝固
|
|
|
|
|
+
|
|
|
|
|
+按更新周期拆表(业界主流 OneData / 字节 / 美团做法):
|
|
|
|
|
+
|
|
|
|
|
+| 后缀 | 写入策略 | 含哪些标签 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `_d` | 每天 INSERT OVERWRITE 单分区 dt=T-1 | 属性 snap + 偏好滚动窗口(30d)+ 偏好当年累计(y{当年})|
|
|
|
|
|
+| `_o` | 一次性写入永远不动 | 偏好往年总额(y{往年},跨年凝固时新建一张)|
|
|
|
|
|
+
|
|
|
|
|
+**为什么分两类**:
|
|
|
|
|
+
|
|
|
|
|
+- y{往年} 一旦凝固永不变,与 _d 日更"每天重刷 T-1"语义冲突 — 混在 _d 表会让"永远不变"的标签被天天扫一遍重写
|
|
|
|
|
+- 各自独立调度:_d 是日 DAG,_o 是手动 once(落 `manual/backfill/`,跑一次写完)
|
|
|
|
|
+
|
|
|
|
|
+### 1.4 写入策略
|
|
|
|
|
+
|
|
|
|
|
+| 表 | dt 锚点 | 写入 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `_d` | T-1(`${dt}`)| `INSERT OVERWRITE TABLE ... PARTITION (dt='${dt}')` 静态单分区 |
|
|
|
|
|
+| `_o` | 凝固年 12-31(如 `20251231`)| `INSERT OVERWRITE TABLE ... PARTITION (dt='20251231')` 静态单分区 |
|
|
|
|
|
+
|
|
|
|
|
+### 1.5 调度依赖
|
|
|
|
|
+
|
|
|
|
|
+- `_d` sche:DS DEPENDENT 同 dt `dim_usr_user_ful_d`(属性源)+ 同 dt `dws_usr_user_trade_1d`(偏好源)
|
|
|
|
|
+- `_o`:不挂日调度,手跑 once
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 2. tdm_usr_tag_d(用户标签 日更长表)
|
|
|
|
|
+
|
|
|
|
|
+### 2.1 用途
|
|
|
|
|
+
|
|
|
|
|
+承载 1 期用户标签的日更部分:7 个属性 + 16 品类 × 4 偏好窗口(30d 金额/次数 + y{当年} 金额/次数)。
|
|
|
|
|
+
|
|
|
|
|
+### 2.2 粒度
|
|
|
|
|
+
|
|
|
|
|
+每个 (entity_id, tag_code) 在 dt 分区内唯一。
|
|
|
|
|
+
|
|
|
|
|
+### 2.3 来源
|
|
|
|
|
+
|
|
|
|
|
+- 属性 7 个 ← `dim_usr_user_ful_d WHERE dt='${dt}'`
|
|
|
|
|
+- 偏好 30d 金额/次数 ← `dws_usr_user_trade_1d WHERE dt BETWEEN $[yyyyMMdd-30] AND ${dt}` 滚动聚合
|
|
|
|
|
+- 偏好 y{当年} 金额/次数 ← `dws_usr_user_trade_1d WHERE dt BETWEEN '{当年}0101' AND ${dt}` 滚动覆盖(1 期当年 = 2026)
|
|
|
|
|
+
|
|
|
|
|
+### 2.4 tag_code 清单
|
|
|
|
|
+
|
|
|
|
|
+#### 属性类(tag_type=attr,7 个)
|
|
|
|
|
+
|
|
|
|
|
+| tag_code | 描述 | 来源 / 算法 | tag_value 格式 |
|
|
|
|
|
+|---|---|---|---|
|
|
|
|
|
+| `usr_level` | 用户等级 | dim_usr_user.member_level | 数字字符串(如 `"3"`)|
|
|
|
|
|
+| `usr_is_cert` | 实名认证情况 | dim_usr_user.is_cert | `"true"` / `"false"` |
|
|
|
|
|
+| `usr_sex` | 性别 | dim_usr_user.sex_cert(未实名 NULL)| `"M"` / `"F"` |
|
|
|
|
|
+| `usr_city` | 城市 | dim_usr_user.cert_city(未实名 NULL)| 城市名 |
|
|
|
|
|
+| `usr_register_time` | 注册时间 | dim_usr_user.reg_create_time | `yyyyMMdd` |
|
|
|
|
|
+| `usr_birth_month` | 生日年月 | dim_usr_user.birthday_cert 派生(未实名 NULL)| `yyyyMM` |
|
|
|
|
|
+| `usr_generation` | 出生世代 | dim_usr_user.birthday_cert 派生(按 §6 切片)| 世代名("90后" / "00后" 等)|
|
|
|
|
|
+
|
|
|
|
|
+#### 偏好类(tag_type=stat,16 品类 × 4 窗口 = 64 个)
|
|
|
|
|
+
|
|
|
|
|
+| tag_code 模板 | 描述 | 来源 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `usr_pref_trade_{category}_amt_30d` | 某品类近 30 天金额 | `SUM(pay_amt_cny)` WHERE dt IN [T-30, T-1] |
|
|
|
|
|
+| `usr_pref_trade_{category}_cnt_30d` | 某品类近 30 天次数 | `SUM(pay_order_cnt)` 同口径 |
|
|
|
|
|
+| `usr_pref_trade_{category}_amt_y2026` | 某品类 26 年累计金额 | `SUM(pay_amt_cny)` WHERE dt IN [20260101, T-1](每天滚动覆盖)|
|
|
|
|
|
+| `usr_pref_trade_{category}_cnt_y2026` | 某品类 26 年累计次数 | `SUM(pay_order_cnt)` 同口径 |
|
|
|
|
|
+
|
|
|
|
|
+`{category}` 是 16 品类占位(kb/28 §3.2 DIM 已清洗):Basketball / Soccer / MLB / TCG / PTCG / 影视收藏 / 综合体育 / 综合收藏 / NFL / NHL / UFC / WWE / Tennis / Esports / F1 / Golf。
|
|
|
|
|
+
|
|
|
|
|
+**金额口径**:`SUM(pay_amt_cny)` = Net Revenue 偏好金额(A3 锁 1 期不扣减退款;GMV = `payable_amt_cny`,偏好 amt 用 pay_amt_cny,见 kb/27 §2.5 / kb/29 §2.5)。
|
|
|
|
|
+
|
|
|
|
|
+**次数口径**:`SUM(pay_order_cnt)` = `COUNT(DISTINCT order_id)`(A2 锁定,1 期不用份数)。
|
|
|
|
|
+
|
|
|
|
|
+### 2.5 字段表
|
|
|
|
|
+
|
|
|
|
|
+按 EAV 7 字段(同 §1.2),dt = `${dt}` = T-1。
|
|
|
|
|
+
|
|
|
|
|
+### 2.6 行数估算
|
|
|
|
|
+
|
|
|
|
|
+- 属性:30 万用户 × 7 = 210 万行
|
|
|
|
|
+- 偏好:30 万用户 × ~5 活跃品类 × 4 窗口 = 600 万行
|
|
|
|
|
+- 合计 ~ 800 万行 / 分区,ORC 压缩后 < 200 MB
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 3. tdm_usr_tag_y2025_o(25 年总额标签 一次性凝固)
|
|
|
|
|
+
|
|
|
|
|
+### 3.1 用途
|
|
|
|
|
+
|
|
|
|
|
+承载 25 年总额标签(16 品类 × 金额 / 次数 = 32 个),开发完一次性跑入永远不动。
|
|
|
|
|
+
|
|
|
|
|
+### 3.2 粒度
|
|
|
|
|
+
|
|
|
|
|
+每个 (entity_id, tag_code) 在 dt=20251231 分区内唯一。
|
|
|
|
|
+
|
|
|
|
|
+### 3.3 来源
|
|
|
|
|
+
|
|
|
|
|
+`dws_usr_user_trade_1d WHERE dt BETWEEN '20250101' AND '20251231'` 一次性聚合。
|
|
|
|
|
+
|
|
|
|
|
+### 3.4 tag_code 清单(tag_type=stat,32 个)
|
|
|
|
|
+
|
|
|
|
|
+| tag_code 模板 | 描述 | 来源 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `usr_pref_trade_{category}_amt_y2025` | 某品类 25 年总额 | `SUM(pay_amt_cny)` WHERE dt IN [20250101, 20251231] |
|
|
|
|
|
+| `usr_pref_trade_{category}_cnt_y2025` | 某品类 25 年总次数 | `SUM(pay_order_cnt)` 同口径 |
|
|
|
|
|
+
|
|
|
|
|
+`{category}` 同 §2.4 16 品类。
|
|
|
|
|
+
|
|
|
|
|
+### 3.5 dt 锚点 + 写入
|
|
|
|
|
+
|
|
|
|
|
+- `dt='20251231'` 永久固定
|
|
|
|
|
+- 跑一次写入后永远不动
|
|
|
|
|
+- 落 `manual/backfill/{yyyymmdd}_tdm_usr_tag_y2025_o.sql` 一次性 SQL,不挂日调度
|
|
|
|
|
+
|
|
|
|
|
+### 3.6 行数估算
|
|
|
|
|
+
|
|
|
|
|
+30 万用户 × ~5 活跃品类 × 2 度量 ≈ 300 万行(永久),ORC 压缩后 < 100 MB。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 4. tag_code 命名约定
|
|
|
|
|
+
|
|
|
|
|
+| 类型 | 模板 | 示例 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| 属性 | `usr_{属性名}` | `usr_sex` / `usr_city` / `usr_generation` |
|
|
|
|
|
+| 偏好 | `usr_pref_{主题}_{category}_{metric}_{window}` | `usr_pref_trade_basketball_amt_30d` / `usr_pref_trade_mlb_cnt_y2025` |
|
|
|
|
|
+
|
|
|
|
|
+**所有维度(品类 / 窗口 / 度量)全部 encode 到 tag_code**。下游按维度切片用 `tag_code LIKE 'usr_pref_trade_%_amt_30d'` 等模式匹配。
|
|
|
|
|
+
|
|
|
|
|
+`{window}` 取值约定:
|
|
|
|
|
+
|
|
|
|
|
+- `snap`(当前快照,T-1 的属性)
|
|
|
|
|
+- `30d`(近 30 天滚动 [T-30, T-1])
|
|
|
|
|
+- `y{yyyy}`(按年累计 / 总额;当年 = _d 表滚动,往年 = _o 表凝固)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 5. 跨年扩张规则
|
|
|
|
|
+
|
|
|
|
|
+每年 1-1 凝固上一年累计为新表:
|
|
|
|
|
+
|
|
|
|
|
+| 时点 | 动作 |
|
|
|
|
|
+|---|---|
|
|
|
|
|
+| 2027-01-01 | 新建 `tdm_usr_tag_y2026_o`(凝固 26 年累计);`tdm_usr_tag_d` 移除 y2026 偏好 tag_code + 新增 y2027 tag_code |
|
|
|
|
|
+| 2028-01-01 | 新建 `tdm_usr_tag_y2027_o`;同理 |
|
|
|
|
|
+
|
|
|
|
|
+`_o` 表数据永久保留。下游想看历年总额按 `dt='{凝固年}1231'` 查对应 `_o` 表。
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 6. 属性细节默认口径(待业务回头校准)
|
|
|
|
|
+
|
|
|
|
|
+按 tdm.md 7 个属性,业务侧未给精确口径前先用合理默认(源字段已在 kb/28 §2 确认);调字段不动 schema(EAV 收益)。
|
|
|
|
|
+
|
|
|
|
|
+| tag_code | 默认口径 | 待业务确认 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `usr_level` | `member_level` | 业务库另有 `level` 字段,两字段语义区别待澄清;1 期取 member_level |
|
|
|
|
|
+| `usr_is_cert` | `is_cert` 布尔 → `"true"` / `"false"` | 是否区分"未实名 / 审核中 / 已实名"3 态?1 期 2 态 |
|
|
|
|
|
+| `usr_sex` | `sex_cert`(M / F),未实名 NULL | 未实名是否回退取自填 sex?1 期 cert 一源 |
|
|
|
|
|
+| `usr_city` | `cert_city`,未实名 NULL | 未实名是否走 login_addr / register_addr?1 期 cert_city 一源 |
|
|
|
|
|
+| `usr_register_time` | `reg_create_time` → `DATE_FORMAT 'yyyyMMdd'` | 是否要月 / 周粒度?1 期日粒度 |
|
|
|
|
|
+| `usr_birth_month` | `birthday_cert` → `DATE_FORMAT 'yyyyMM'`,未实名 NULL | 是否只取月(MM)?1 期 yyyyMM 留年信息 |
|
|
|
|
|
+| `usr_generation` | `birthday_cert` 派生 10 年切片:60 前 / 60 后 / 70 后 / 80 后 / 85 后 / 90 后 / 95 后 / 00 后 / 05 后 / 10 后 | 切片粒度(5 年 / 10 年)?切片名(中文"90后" / 英文"1990s")?1 期中文 N 后 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 7. 不在 1 期 scope
|
|
|
|
|
+
|
|
|
|
|
+- **TDM 宽表** `tdm_usr_profile_ful_d`:1 期标签未完善(业界规范长表稳定后再做宽表,见 kb/23 §3.2),2 期再评估
|
|
|
|
|
+- **TDM 人群包** `tdm_usr_crowd_ful_d`:1 期不做圈选
|
|
|
|
|
+- **商品标签 / 店铺标签**:tdm.md mermaid 图的 C / D 分支,1 期 scope 外
|
|
|
|
|
+- **algo 类标签**:`tag_type` 预留枚举值,1 期无实际数据;将来接 RFM / 用户生命周期预测等 ML 标签时启用
|