Files
Neo-ZQYY/docs/database/BD_Manual_20260301_cleanup_and_fixes.md

9.8 KiB
Raw Blame History

BD 手册assistant_trash_event 清理 + ODS_STORE_GOODS_SALES 修复 + dim_staff_ex 修复 + DWS 精度扩展 + ODS 库存 siteid 注入

日期2026-03-01 Prompt 摘要:清理 assistant_trash_event 残留代码/DDL 文档;修复 ODS_STORE_GOODS_SALES 窗口配置以恢复商品销售数据拉取;修复 dim_staff_ex FACT_MAPPINGS 列名映射错误DWS 层 7 个 ratio/margin 字段 numeric 精度扩展P1ODS goods_stock_summary 加 siteid 列 + DWD 映射补全P2 直接原因:联调发现的 P1/P2 问题 + 三个独立问题的批量修复


一、变更说明

1.1 assistant_trash_event 残留清理

dwd.dwd_assistant_trash_eventdwd.dwd_assistant_trash_event_ex 已于 2026-02-22 DROP 上游 ODS 表 ods.assistant_cancellation_records 同步 DROP。本次清理残留的代码引用和 DDL 文档。

DDL 文档删除项:

文件 删除内容
etl_feiqiu__ods.sql PK 约束 assistant_cancellation_records_pkey,索引 idx_assistant_cancellation_records_fetched_at_*2 条)
etl_feiqiu__dwd.sql PK 约束 dwd_assistant_trash_event_pkeydwd_assistant_trash_event_ex_pkey,索引 idx_dwd_assistant_trash_event_*2 条)
dwd-amount-duration-calibration.md 章节 2.11(助教废除事件主表)、存疑字段 #15、数据新鲜度行

代码删除项(前序已完成):

  • utils/json_store.py — API 路径映射
  • tasks/utility/manual_ingest_task.py — FILE_MAPPING / TABLE_SPECS
  • quality/consistency_checker.py — ODS_TABLE_TO_JSON_FILE / ODS_TABLE_TO_TASK_CODE
  • scripts/refresh_json_and_audit.py — ACTUAL_LIST_KEY
  • scripts/run_compare_v3.py / run_compare_v3_fixed.py — TABLES 列表

1.2 ODS_STORE_GOODS_SALES 窗口配置修复

问题: ods_tasks.pyODS_STORE_GOODS_SALESrequires_window=False,导致 API /TenantGoods/GetGoodsSalesList 不传 startTime/endTime 参数,始终返回 0 条记录。

修复:

  • requires_windowTrue
  • 新增 time_fields=("startTime", "endTime")

数据恢复: 以 30 天窗口切分,回填 2025-07-07 ~ 2026-03-01ODS 新增 26,759 条DWD 层 dwd_store_goods_sale 从 17,563 → 26,759 条,时间范围延伸至 2026-02-25。

1.3 dim_staff_ex FACT_MAPPINGS 列名修复

问题: dwd_load_task.pydim_staff_ex 的 FACT_MAPPINGS 使用驼峰列名(cashierpointidgroupid 等),但 ODS 表 staff_info_master 实际列名为下划线风格(cashier_point_idgroup_id 等),导致 SCD2 合并 SQL 执行报错,整表被跳过。

修复映射:

DWD 列 修复前(错误) 修复后(正确)
cashier_point_id cashierpointid cashier_point_id
cashier_point_name cashierpointname cashier_point_name
group_id groupid group_id
group_name groupname group_name
system_user_id systemuserid system_user_id
tenant_org_id tenantorgid tenant_org_id
user_roles userroles user_roles

数据恢复: DWD 装载后 dim_staff_ex 从 0 行 → 15 行。

1.4 [P1] DWS 层 numeric 精度扩展(举一反三)

问题: dws.dws_assistant_finance_analysis.gross_margin 定义为 numeric(5,4),只能存 ±0.9999。当 cost_daily > revenue_total(亏损场景),gross_margin = gross_profit / revenue_total 可能 < -1导致 INSERT 溢出报错。举一反三排查发现 7 个同类风险字段。

修复:

字段 修复前 修复后
dws.cfg_performance_tier bonus_deduction_ratio numeric(5,4) numeric(7,4)
dws.dws_assistant_finance_analysis gross_margin numeric(5,4) numeric(7,4)
dws.dws_assistant_recharge_commission commission_ratio numeric(5,4) numeric(7,4)
dws.dws_assistant_salary_calc bonus_deduction_ratio numeric(5,4) numeric(7,4)
dws.dws_finance_discount_detail discount_ratio numeric(5,4) numeric(7,4)
dws.dws_finance_income_structure income_ratio numeric(5,4) numeric(7,4)
dws.dws_member_assistant_intimacy burst_multiplier numeric(6,4) numeric(7,4)

依赖视图处理: 7 个 app.v_dws_* RLS 视图先 DROP 再重建。

Python 防御: assistant_finance_task.pygross_margin 计算加 clamp 到 ±999.9999。

迁移脚本: db/etl_feiqiu/migrations/20260301_dws_numeric_precision_fix.sql

1.5 [P2] ODS goods_stock_summary 加 siteid + DWD 映射补全

问题: dwd.dwd_goods_stock_summary DDL 定义了 site_id biginttenant_id bigint,但 FACT_MAPPINGS 缺少映射,导致 DWD 层 site_id 始终为 NULL。

根因分析:

  • API GetGoodsStockReport 返回的记录不含 siteId/tenantId(已从 JSON 缓存确认)
  • ODS 表 ods.goods_stock_summary 也没有 siteid
  • 请求参数中有 siteId,但 ODS 入库时未注入到记录中

修复(三层联动):

  1. ODS 表加列:ALTER TABLE ods.goods_stock_summary ADD COLUMN siteid bigint
  2. ODS 入库通用注入:_insert_records_schema_aware 中,当 ODS 表有 siteid 列但记录不含时,从 app.store_id 配置注入
  3. DWD FACT_MAPPINGS 补映射:("site_id", '"siteid"', "bigint")
  4. 已有数据回填:从 ods.goods_stock_movements 推断 siteid 回填 3216 条

迁移脚本: db/etl_feiqiu/migrations/20260301_ods_goods_stock_summary_add_siteid.sql


二、兼容性影响

子系统 影响
ETL assistant_trash_event 相关任务已无代码引用,无影响;ODS_STORE_GOODS_SALES 恢复正常窗口拉取;dim_staff_ex 恢复正常 SCD2 装载DWS ratio 字段精度扩展后不再溢出ODS 库存汇总入库时自动注入 siteid
后端 API 7 个 app.v_dws_* RLS 视图已重建,字段类型从 numeric(5,4) 变为 numeric(7,4)API 返回值精度不变(仍为 4 位小数),无破坏性影响
小程序 无影响
管理后台 商品销售相关报表数据将恢复完整;库存汇总将携带 site_id

三、回滚策略

3.1 assistant_trash_event

纯文档清理,无需回滚。如需恢复,从 git 历史还原对应行即可。

3.2 ODS_STORE_GOODS_SALES

# 回滚 ods_tasks.py
requires_window=True    requires_window=False
# 删除 time_fields=("startTime", "endTime") 行

3.3 dim_staff_ex

# 回滚 dwd_load_task.py FACT_MAPPINGS
("cashier_point_id", "cashier_point_id", "bigint")    ("cashier_point_id", "cashierpointid", "bigint")
# 其余 6 个字段同理恢复驼峰写法

如需清空已装载数据:TRUNCATE dwd.dim_staff_ex;

3.4 [P1] DWS numeric 精度

-- 回滚脚本db/etl_feiqiu/migrations/20260301_dws_numeric_precision_fix_rollback.sql
-- 注意:如果已有数据超出原精度范围(如 gross_margin > 0.9999),回滚会失败
-- 需先清理超范围数据:
UPDATE dws.dws_assistant_finance_analysis SET gross_margin = LEAST(0.9999, GREATEST(-0.9999, gross_margin));
-- 然后执行回滚(同样需要先 DROP 再重建视图)

Python 回滚:删除 assistant_finance_task.py 中的 clamp 行。

3.5 [P2] ODS siteid 列

-- ODS 列不可逆删除(已有数据依赖),但可置 NULL
UPDATE ods.goods_stock_summary SET siteid = NULL;
-- DWD FACT_MAPPINGS 回滚:删除 ("site_id", '"siteid"', "bigint") 行
-- ODS 入库注入回滚:删除 ods_tasks.py 中 "通用 siteid 注入" 代码块

四、验证 SQL

-- 1. 确认 assistant_trash_event 表已不存在
SELECT count(*) FROM information_schema.tables
WHERE table_schema = 'dwd' AND table_name LIKE '%assistant_trash_event%';
-- 预期0

-- 2. 确认 ODS 商品销售数据已回填
SELECT count(*) as cnt, min(create_time) as min_time, max(create_time) as max_time
FROM ods.store_goods_sales_records WHERE fetched_at IS NOT NULL;
-- 预期cnt > 40000, max_time >= 2026-02-25

-- 3. 确认 DWD 商品销售数据已更新
SELECT count(*) as cnt, max(create_time) as max_time FROM dwd.dwd_store_goods_sale;
-- 预期cnt > 25000, max_time >= 2026-02-25

-- 4. 确认 dim_staff_ex 已有数据
SELECT count(*) as cnt FROM dwd.dim_staff_ex WHERE scd2_is_current = 1;
-- 预期cnt = 15与 dim_staff 一致)

-- 5. 确认 dim_staff_ex 关键字段非全 NULL
SELECT count(*) as has_system_user FROM dwd.dim_staff_ex
WHERE scd2_is_current = 1 AND system_user_id IS NOT NULL;
-- 预期:> 0

-- 6. [P1] 确认 DWS ratio 字段精度已扩展
SELECT table_name, column_name, numeric_precision, numeric_scale
FROM information_schema.columns
WHERE table_schema = 'dws'
  AND column_name IN ('gross_margin', 'bonus_deduction_ratio', 'commission_ratio',
                      'discount_ratio', 'income_ratio', 'burst_multiplier')
ORDER BY table_name;
-- 预期:所有行 numeric_precision=7, numeric_scale=4

-- 7. [P1] 确认 RLS 视图已重建
SELECT table_schema || '.' || table_name FROM information_schema.views
WHERE table_schema = 'app'
  AND table_name IN ('v_cfg_performance_tier', 'v_dws_assistant_finance_analysis',
                     'v_dws_assistant_recharge_commission', 'v_dws_assistant_salary_calc',
                     'v_dws_finance_discount_detail', 'v_dws_finance_income_structure',
                     'v_dws_member_assistant_intimacy');
-- 预期7 行

-- 8. [P2] 确认 ODS goods_stock_summary 有 siteid 列且已回填
SELECT count(*) as total, count(siteid) as filled, count(DISTINCT siteid) as distinct_sites
FROM ods.goods_stock_summary;
-- 预期filled = total, distinct_sites = 1

-- 9. [P2] 确认 DWD FACT_MAPPINGS 生效(下次 DWD_LOAD 后验证)
SELECT count(*) as has_site_id FROM dwd.dwd_goods_stock_summary WHERE site_id IS NOT NULL;
-- 预期:下次 ETL 运行后 > 0当前可能仍为 0需重跑 DWD_LOAD