perf(db): 补齐三处"只差索引"的热查询缺口
审计方式:pg_stat_statements 按"每次调用读取块数"排序 + EXPLAIN (ANALYZE, BUFFERS) 复现, 每条都先在线上并发建索引验证有效再固化(生产上索引已存在,IF NOT EXISTS 跳过)。 ① 后台订单列表:COALESCE(paid_at, created_at) 同时出现在 WHERE 与 ORDER BY, 函数包裹列非 sargable —— 默认"近 7 天"视角本身就会全表扫 orders 再排序。 实测 26 万行/443MB:Parallel Seq Scan 读 256MB、577ms → Index Scan 读 0.3MB、2.05ms(约 280 倍)。 ② 重跑快手补单:NOT EXISTS 打在 work_orders.order_id 上,而该列此前**没有索引**, 反连接只能 Hash Anti Join —— 为几十个候选 id 顺序扫完 500MB 宽表,LIMIT 100 拦不住。 实测 188MB、120ms → Index Only Scan 1.2ms(约 100 倍)。同时补 orders(order_status)。 ③ 快手凭证"同步源"列表的 (oid, updated_at DESC, id DESC):29.6 万行/678MB,实测 568MB、5.5 秒。 仅建索引不足以改变计划(查询写法要求先物化全部 oid,见审计报告),但它是后续 改写查询的前提,先建好避免再等一次大表建索引。 验证:后端 534 项单测全绿(新增 1 项守卫)。
This commit is contained in:
@@ -2684,3 +2684,31 @@ test('按运营态筛选的计数必须有覆盖索引(生产实测每次读 2
|
||||
'迁移在事务内执行,不能使用 CONCURRENTLY',
|
||||
)
|
||||
})
|
||||
|
||||
test('三处"只差索引"的热查询缺口必须有迁移兜底(生产已前后对比验证)', async () => {
|
||||
const { readFile } = await import('node:fs/promises')
|
||||
const migration = await readFile(
|
||||
new URL('../../db/migrations/086_verified_hot_query_indexes.sql', import.meta.url),
|
||||
'utf8',
|
||||
)
|
||||
// ① 后台订单列表:COALESCE 表达式索引,否则默认 7 天视角就全表扫 orders(实测 256MB/577ms)
|
||||
assert.ok(
|
||||
/idx_orders_effective_ordered_at[\s\S]*?COALESCE\(paid_at, created_at\)/.test(migration),
|
||||
'缺少 orders 的 COALESCE(paid_at, created_at) 表达式索引',
|
||||
)
|
||||
// ② 重跑快手补单:work_orders.order_id 此前完全没有索引(实测 188MB 全表扫)
|
||||
assert.ok(
|
||||
/idx_work_orders_order_id[\s\S]*?\(order_id\)/.test(migration),
|
||||
'缺少 work_orders(order_id) 索引',
|
||||
)
|
||||
assert.ok(migration.includes('idx_orders_order_status'), '缺少 orders(order_status) 索引')
|
||||
// ③ 快手凭证同步源去重排序
|
||||
assert.ok(
|
||||
/idx_kuaishou_vouchers_oid_updated[\s\S]*?\(oid, updated_at DESC, id DESC\)/.test(migration),
|
||||
'缺少 kuaishou_industry_vouchers(oid, updated_at DESC, id DESC) 索引',
|
||||
)
|
||||
assert.ok(
|
||||
!/^\s*CREATE INDEX CONCURRENTLY/m.test(migration),
|
||||
'迁移在事务内执行,不能使用 CONCURRENTLY',
|
||||
)
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user