perf(db): 收入口径回填改为分批脚本
迁移 104 里对 order_items 的全表 UPDATE 实测 34.4 秒(375,447 行), 远超默认语句超时 15s,单事务迁移会拖住启动甚至直接失败。 - 104 只保留 DDL 与索引/约束,删除全表 UPDATE; - 新增 scripts/backfill-revenue-basis.ts:按 id 分批、幂等、支持 --dry-run / --batch-size / --max-batches(kebab 与 camel 两种写法); - package.json 增加 revenue:backfill; - migrate.ts 启动时做一次带索引计数,仍有 unknown 时打印告警并给出命令, 不阻塞启动; - 文档补充回填步骤与「不执行的后果」。 验证: - 实测 37.5 万行全表更新 34.4s → 脚本按批执行,单批 5000 行; - 功能验证:单条订单项置 unknown → 脚本回填 → 金额与 basis 恢复正确; - 启动告警验证:保留 1 条 unknown 重启 → 日志出现告警;回填后计数归零; - 全新库从 102 迁移到 107 仍成功(2s)。
This commit is contained in:
@@ -317,35 +317,11 @@ BEGIN
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- 历史订单回填:当前生产快照全部是一单一品,仍按通用规则处理多订单项。
|
||||
-- 幂等:只处理 revenue_basis 仍为 unknown 的行,重复执行不会二次拆分。
|
||||
WITH item_counts AS (
|
||||
SELECT order_id, COUNT(*)::int AS item_count
|
||||
FROM order_items
|
||||
GROUP BY order_id
|
||||
),
|
||||
ranked AS (
|
||||
SELECT
|
||||
oi.id,
|
||||
GREATEST(COALESCE(o.total_amount, 0), 0)::bigint AS order_revenue_fen,
|
||||
ic.item_count,
|
||||
ROW_NUMBER() OVER (PARTITION BY oi.order_id ORDER BY oi.id ASC) AS item_rank
|
||||
FROM order_items oi
|
||||
JOIN orders o ON o.id = oi.order_id
|
||||
JOIN item_counts ic ON ic.order_id = oi.order_id
|
||||
)
|
||||
UPDATE order_items oi
|
||||
SET
|
||||
revenue_amount_fen = CASE
|
||||
WHEN r.item_count = 1 THEN r.order_revenue_fen
|
||||
ELSE (r.order_revenue_fen / r.item_count)
|
||||
+ CASE WHEN r.item_rank = r.item_count THEN (r.order_revenue_fen % r.item_count) ELSE 0 END
|
||||
END,
|
||||
revenue_basis = CASE WHEN r.item_count = 1 THEN 'order_total' ELSE 'equal_split' END,
|
||||
updated_at = NOW()
|
||||
FROM ranked r
|
||||
WHERE oi.id = r.id
|
||||
AND oi.revenue_basis = 'unknown';
|
||||
-- 历史订单的收入回填**不在迁移里做**。
|
||||
-- 实测:375,447 行的全表 UPDATE 需要约 34 秒,远超默认语句超时
|
||||
-- (DATABASE_STATEMENT_TIMEOUT_MS=15s),放进单事务迁移会拖住启动甚至直接失败。
|
||||
-- 改由 `npm run revenue:backfill` 分批执行(幂等、可续跑、支持 --dry-run);
|
||||
-- 应用启动时若仍有 revenue_basis='unknown' 的行,会打印告警提示执行该命令。
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_order_items_revenue_basis
|
||||
ON order_items (revenue_basis);
|
||||
|
||||
Reference in New Issue
Block a user