perf(worker): 单号检索收敛为可走索引的等值/前缀,并支持关联单号反查
问题:后台「按单号检索」在平台单号/工单号分支里 OR 了一支
`work_order_no ILIKE '%'||$n||'%'`。前置通配符非 sargable,任何 B-Tree 都用不上,
整条查询退化成 work_orders 的 Seq Scan。
生产实测(10.3 万行 / 572MB,pg_stat_statements 46 小时窗口):
- 列表查询 + 统计查询用同一份 filters 并行执行,一次检索打两遍全表;
两者合计占全库 66% 的磁盘读(1.1TB/46h),单次读 26,442 个块(约 211MB)、398ms、返回 1 行。
- 收敛后同库同参数:等值 0.19ms,前缀 30ms(约 2000 倍)。
- 真实统计查询端到端 760ms → 61.6ms。
改动:
1. 平台单号/工单号分支收敛为「等值 + 前缀」,与 order-repo / task-repo 既有写法一致;
工单号含随机小写段(10.2 万行里 7.4 万行非全大写),保留 LOWER() 比较。
2. 迁移 090 补 text_pattern_ops 前缀索引:当前库 collation 为 en_US.utf8,
前缀 LIKE 在默认 B-Tree 上会退化成全索引扫(实测 438ms)。
3. 新增关联单号反查分支:SUB/INV/AS/DT 不在 work_orders 上,
经关联表反查工单 id,四条链路均命中唯一索引。
4. 前端 isExplicitOrderNoSearch 同步补齐(否则搜到的单会被状态页签挡掉、
实时补丁还会把行删掉)。
验证:生产 EXPLAIN 逐条比对 + 14 项仓储单测 + 6 项分类器单测。
This commit is contained in:
@@ -100,11 +100,15 @@ function matchesCreatedRange(
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否为「显式单号检索」——工单号 / 平台单号 / 纯数字单号。
|
||||
* 是否为「显式单号检索」——工单号 / 平台单号 / 纯数字单号 / 关联单号。
|
||||
*
|
||||
* 两处依赖它,必须保持一致,所以放在这里而不是面板内部:
|
||||
* 1. 面板搜索时据此清空排他的状态/阶段筛选(避免流转后单子脱靶);
|
||||
* 2. 实时补丁判定据此短路为「只原地更新」,绝不把正在看的单删掉。
|
||||
*
|
||||
* 关联单号(寄卖提报号 SUB / 仓库号 INV / 售后案号 AS / 履约任务号 DT)与后端
|
||||
* work-order-query-repo 的反查分支一一对应:客服界面「只认寄卖单号」,
|
||||
* 粘进来的就是 SUB,漏掉它会导致搜到的单被状态页签挡掉。
|
||||
*/
|
||||
export function isExplicitOrderNoSearch(text: unknown): boolean {
|
||||
const trimmed = String(text || '').trim()
|
||||
@@ -112,7 +116,11 @@ export function isExplicitOrderNoSearch(text: unknown): boolean {
|
||||
return (
|
||||
/^WO[0-9a-zA-Z]{4,}$/i.test(trimmed) ||
|
||||
/^\d{6,}(-\d{6,})?$/.test(trimmed) ||
|
||||
/^OD[0-9a-zA-Z]{4,}$/i.test(trimmed)
|
||||
/^OD[0-9a-zA-Z]{4,}$/i.test(trimmed) ||
|
||||
/^SUB\d{8,}$/i.test(trimmed) ||
|
||||
/^INV\d{8,}$/i.test(trimmed) ||
|
||||
/^AS[0-9a-f]{8,}$/i.test(trimmed) ||
|
||||
/^DT[0-9a-f]{8,}$/i.test(trimmed)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user