优化接单平台工单查询性能

This commit is contained in:
yml2213
2026-09-04 21:22:35 +08:00
parent 625df52992
commit 84a8f138d4
7 changed files with 158 additions and 82 deletions
+48 -2
View File
@@ -10,7 +10,12 @@ import { fileURLToPath } from 'node:url'
const SCRIPT_DIR = path.dirname(fileURLToPath(import.meta.url))
const BACKEND_ROOT = path.resolve(SCRIPT_DIR, '..')
const checks: Array<{ name: string; file: string; patterns: string[] }> = [
const checks: Array<{
name: string
file: string
patterns?: string[]
forbiddenPatterns?: string[]
}> = [
{
name: '慢查询阈值配置',
file: path.join(BACKEND_ROOT, 'src/config/env-overrides.ts'),
@@ -35,6 +40,12 @@ const checks: Array<{ name: string; file: string; patterns: string[] }> = [
file: path.join(BACKEND_ROOT, 'src/repositories/worker-platform/work-order-share-repo.ts'),
patterns: ['workOrderIds: number[]', 'wos.work_order_id = ANY($2::bigint[])'],
},
{
name: '接单工单宽详情分页禁止窗口总数',
file: path.join(BACKEND_ROOT, 'src/repositories/worker-platform/work-order-query-repo.ts'),
patterns: ['countWorkOrdersWithWhere', 'includeTotal'],
forbiddenPatterns: ['COUNT(*) OVER' + '()', 'LIST_WORK_ORDER_SELECT'],
},
{
name: '数据保留清理扫描索引',
file: path.join(BACKEND_ROOT, 'src/db/migrations/067_data_retention_indexes.sql'),
@@ -55,10 +66,27 @@ const checks: Array<{ name: string; file: string; patterns: string[] }> = [
"WHERE event_type LIKE 'timeout_%'",
],
},
{
name: '接单工单搜索表达式索引重建',
file: path.join(BACKEND_ROOT, 'src/db/migrations/073_rebuild_work_order_search_index.sql'),
patterns: [
'DROP INDEX IF EXISTS idx_work_orders_search_text_trgm',
'CREATE INDEX idx_work_orders_search_text_trgm',
"material_json->'collect'->'fields'->>'gameId'",
],
},
]
const failures: string[] = []
// 窗口总数会在 LIMIT/OFFSET 之前消费全部候选行;全后端 SQL 都禁止引入该写法。
const countWindowPattern = /COUNT\s*\(\s*\*\s*\)\s*OVER\s*\(/i
for (const file of listSourceFiles(path.join(BACKEND_ROOT, 'src'))) {
if (countWindowPattern.test(fs.readFileSync(file, 'utf8'))) {
failures.push(`禁止 COUNT(*) OVER() 窗口分页: ${file}`)
}
}
// 已应用的历史迁移必须保持字节不变,所有结构或数据修复都必须新增迁移文件。
try {
const diffOutputs = [
@@ -89,11 +117,16 @@ for (const check of checks) {
continue
}
const source = fs.readFileSync(check.file, 'utf8')
for (const pattern of check.patterns) {
for (const pattern of check.patterns || []) {
if (!source.includes(pattern)) {
failures.push(`${check.name}: 缺少约束 ${pattern} (${check.file})`)
}
}
for (const pattern of check.forbiddenPatterns || []) {
if (source.includes(pattern)) {
failures.push(`${check.name}: 出现禁止 SQL ${pattern} (${check.file})`)
}
}
}
if (failures.length > 0) {
@@ -103,3 +136,16 @@ if (failures.length > 0) {
} else {
console.info('[sql-guard] SQL 约束检查通过')
}
function listSourceFiles(directory: string): string[] {
const files: string[] = []
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
const file = path.join(directory, entry.name)
if (entry.isDirectory()) {
files.push(...listSourceFiles(file))
} else if (entry.isFile() && /\.(?:ts|sql)$/.test(entry.name)) {
files.push(file)
}
}
return files
}