perf(db): 高频查询补索引 + 大列表加合理上限(避免全表下发)

- 启动建表后幂等补索引:orders/finance_records/users/reports/companions/payment_intents/payment_refunds 等高频查询列

- 管理端订单/财务流水/用户列表 LIMIT 500,友圈/评价列表 LIMIT 200,防止无界查询

- expert_services 懒建表后补 expert_id 索引

- 新增回归护栏 list-pagination-index.spec.ts(84 套件/625 用例全绿)
这个提交包含在:
xcbyy
2026-10-19 09:28:02 +08:00
父节点 d665cd6976
当前提交 cbf77a7252
共有 3 个文件被更改,包括 99 次插入 和 3 次删除

查看文件

@@ -271,6 +271,7 @@ export async function initDatabase(): Promise<void> {
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 8. 线下合规场所库
await conn.query(`
CREATE TABLE IF NOT EXISTS safety_places (
@@ -644,6 +645,56 @@ export async function initDatabase(): Promise<void> {
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
`);
// 慢查询优化:为高频查询列补充索引(幂等:已存在则忽略;表不存在也忽略)
// 注意:必须在所有建表语句之后执行,确保目标表已存在。
const indexDefs: Array<[string, string, string]> = [
['orders', 'idx_orders_buyer', 'buyer_id'],
['orders', 'idx_orders_expert', 'expert_id'],
['orders', 'idx_orders_claimed_by', 'claimed_by'],
['orders', 'idx_orders_status_created', 'status, created_at'],
['orders', 'idx_orders_verify_code', 'verify_code'],
['orders', 'idx_orders_companion_name', 'companion_name'],
['order_reviews', 'idx_reviews_expert_created', 'expert_id, created_at'],
['finance_records', 'idx_fin_user', 'user_id'],
['finance_records', 'idx_fin_related', 'related_id'],
['finance_records', 'idx_fin_type', 'type'],
['finance_records', 'idx_fin_created', 'created_at'],
['favorites', 'idx_fav_user', 'user_id'],
['favorites', 'idx_fav_expert', 'expert_id'],
['distribution_records', 'idx_dist_created', 'created_at'],
['posts', 'idx_posts_status_top_created', 'status, is_top, created_at'],
['posts', 'idx_posts_category', 'category'],
['reports', 'idx_reports_status', 'status'],
['reports', 'idx_reports_reporter', 'reporter_id'],
['withdrawals', 'idx_wd_companion', 'companion_id'],
['withdrawals', 'idx_wd_status', 'status'],
['activities', 'idx_act_creator', 'creator_id'],
['activities', 'idx_act_status', 'status'],
['payment_intents', 'idx_pi_order', 'order_id'],
['payment_intents', 'idx_pi_status', 'status'],
['users', 'idx_users_phone', 'phone'],
['users', 'idx_users_inviter', 'inviter_id'],
['users', 'idx_users_nickname', 'nickname'],
['participants', 'idx_pt_user', 'user_id'],
['post_likes', 'idx_post_likes_post', 'post_id'],
['post_comments', 'idx_pc_post', 'post_id'],
['post_applies', 'idx_pa_post', 'post_id'],
['post_applies', 'idx_pa_status', 'status'],
['arbitrations', 'idx_arb_status', 'status'],
['arbitrations', 'idx_arb_order', 'order_id'],
['companions', 'idx_comp_user', 'user_id'],
['companions', 'idx_comp_status', 'status'],
['companions', 'idx_comp_audit', 'audit_status'],
['payment_refunds', 'idx_pr_order', 'order_id'],
];
for (const [table, name, cols] of indexDefs) {
try {
await conn.query(`ALTER TABLE \`${table}\` ADD INDEX \`${name}\` (${cols})`);
} catch (_) {
// 索引已存在或表不存在:忽略
}
}
// 检查并插入初始种子数据(若表为空)
await seedInitialDataIfEmpty(conn);