80f3b21e953d33349310e04eb3631b83d8dd9306
0012 —— 删的都是 Django 建的,列是某个复合索引的最左前缀,规划器本来就走那一个, 多出来的只是每次写入多维护一棵树:17 个前缀被覆盖的、3 个 _like(text_pattern_ops) 副本、1 个同表同列的完全重复(problemset_submission.user_id 上有两个)。 索引 107 → 86 个,32MB → 29MB。 删之前逐条确认过复合索引的第一列就是被删索引的那一列,删之后 19 条代表性查询的 执行计划逐条对过,没有一条退化成 Seq Scan,只是换了覆盖它的那个索引;级联删除会 用到的外键检查路径也都还有索引可走。 0013 —— 拿 auto_explain 把 60 多个读接口打一遍抓出来的真实慢查询,候选索引一个个 建出来实测: - submission (language, create_time) WHERE contest_id IS NULL — 3.2MB 语言筛选原来一个索引都没有,count 固定 75~82ms / 18448 buffers,筛什么值都一样。 改后 Python3(占 8 成)80 → 11ms、C 77 → 1.6ms、SQL 82 → 0.06ms。更要命的是冷门 语言翻页:Python2 只有 3 条全是 2022 年的,分页索引得从最新倒扫到底,43ms 全表扫 → 0.02ms - submission (result, create_time) WHERE contest_id IS NULL — 3.2MB count result=-1 75 → 2.0ms、result=-2 36 → 1.0ms - submission (user_id, problem_id, result, create_time) WHERE contest_id IS NULL — 4.2MB 覆盖索引,给「在全部公开提交上做聚合」那几个接口。它们慢的不是聚合本身,是为了读 这四个小列把 145MB 的堆翻一遍(code 和 info 占了这张表绝大部分体积,聚合一列都用 不上)。走 Index Only Scan 只读 6MB:教师统计全站 186 → 49ms(消掉 4.2MB 落盘 排序)、活跃榜 108 → 18ms、AC 趋势 120 → 41ms - flowchart_submission (create_time) — 64kB 列表分页从 hash join 全表再 top-N 排序(4.5ms / 551 buffers)变成 0.19ms / 47 全列 ASC NULLS LAST 靠反向扫,理由同 submission_public_create_time_id_idx 那段注释。 动手前把三种写法在库上对了一遍:两列 ASC 和 create_time DESC NULLS FIRST 一样快, 写成 DESC NULLS LAST 规划器直接不认这条索引、回落到分页索引带 Filter,注释没说错。 回归检查:不带筛选的列表和深翻页仍然走 submission_public_create_time_id_idx,没被 新索引抢走。submission_result_37e2f67a 留着并补了注释 —— 它看着像被新的部分索引 覆盖了,但那条带 WHERE contest_id IS NULL,管不了全库含比赛按 result 统计(实测删掉 之后 count(*) where result in (6,7) 从走索引掉回 75ms 全表扫)。 两条迁移都在生产结构副本和本机 dev 库各跑过一遍。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KqjE6qPo67fqVDKn6Bx7yd
Description
No description provided
Languages
TypeScript
58.5%
Vue
39.6%
Shell
1.3%
Dockerfile
0.5%