perf: reduce worker order list query load

This commit is contained in:
yml2213
2026-08-30 16:40:09 +08:00
parent a45d7597fb
commit d24c69141a
8 changed files with 223 additions and 117 deletions
@@ -110,6 +110,12 @@ test('后台接单工单支持按接单分类筛选', () => {
assert.deepEqual(query.params, [7])
})
test('空白搜索词不生成全表 LIKE 条件', () => {
const query = buildWorkOrderWhere({ keyword: ' ' })
assert.doesNotMatch(query.whereClause, /LIKE LOWER/)
assert.deepEqual(query.params, [])
})
test('大厅候选按分类上限取队首后再受全局上限限制', () => {
const query = buildWorkOrderWhere({
hallCandidateLimit: 20,
@@ -58,6 +58,13 @@ export const WORK_ORDER_SELECT = `
) share_summary ON TRUE
`
// Keep the page and total in one filtered query. This avoids running the same
// joins and share aggregation twice for every list request.
const LIST_WORK_ORDER_SELECT = WORK_ORDER_SELECT.replace(
' SELECT\n',
' SELECT\n COUNT(*) OVER()::int AS total_count,\n',
)
type WorkerOrderOverviewRow = {
status: string
order_count: number
@@ -268,15 +275,6 @@ export async function listWorkOrders({
createdFrom,
createdTo,
})
const totalResult = await query<{ total: number }>(
`
SELECT COUNT(*)::int AS total
FROM work_orders wo
${joins}
${whereClause}
`,
params,
)
const offset = (page - 1) * pageSize
const orderBy =
sort === 'worker_claimed_at_desc' && workerSharingId
@@ -292,14 +290,30 @@ export async function listWorkOrders({
const effectiveOrderBy = pinnedFirst ? `wo.pinned_at DESC NULLS LAST, ${orderBy}` : orderBy
params.push(pageSize, offset)
const itemsResult = await query<WorkOrderRow>(
`${WORK_ORDER_SELECT}
`${LIST_WORK_ORDER_SELECT}
${joins}
${whereClause}
ORDER BY ${effectiveOrderBy}
LIMIT $${params.length - 1} OFFSET $${params.length}`,
params,
)
return { items: itemsResult.rows, total: Number(totalResult.rows[0]?.total || 0) }
// A page beyond the end has no row from which to read the window count.
// Keep that uncommon pagination edge case correct without restoring a
// second query for normal requests.
let total = Number(
(itemsResult.rows[0] as WorkOrderRow & { total_count?: number })?.total_count || 0,
)
if (itemsResult.rows.length === 0 && page > 1) {
const totalResult = await query<{ total: number }>(
`SELECT COUNT(*)::int AS total FROM work_orders wo ${joins} ${whereClause}`,
params.slice(0, -2),
)
total = Number(totalResult.rows[0]?.total || 0)
}
return {
items: itemsResult.rows,
total,
}
}
/** 按筛选条件汇总工单,统计范围不受当前分页影响。 */