八股 ①:索引与执行计划 20 问
第一步:把这八周踩过的性能知识点,变成能脱口而出的 60–90 秒口述。
学 · 20 min
练 · 100 min
- 把页面底部「性能与索引」8 问 + 自己补 12 问,写成 20 题
参考答案
页面 8 问之外,自补 12 问按三类分:① 原理(B-tree 为什么快、PG 的索引与堆是什么关系);② 失效场景(列上套函数、前导 % 模糊、<>、类型不匹配);③ 实战(EXPLAIN 怎么读、cost 估算和 actual 偏差说明统计信息过期、三种 join 算法的选择依据、索引的写放大代价)。每题先写一句话答案钉住结论,口述稿再扩。
- 每题写一份 60–90 秒的口述稿
参考答案
60–90 秒 ≈ 200–280 字,四段结构:结论先行(一句话)→ 原因(为什么成立)→ 例子(必须用自己在 100 万行 orders 上跑出的真实数字)→ 边界(什么时候不成立)。「大概几秒」这种模糊话一追问就穿帮。
- 录音,回放,标出讲得别扭的地方(那就是没想清楚的地方)
参考答案
回放三查:① 嗯啊超过 3 秒的卡壳处 = 那里没想清楚,标时间戳;② 口头禅(「然后」「就是说」)出现的频次;③ 超过 90 秒的题 = 该砍例子了。
- 重讲一遍被标记的题
参考答案
只重讲被标记的题:脱稿、计时、一次讲到位。隔天再抽查一遍讲过的题——隔天还能流畅讲出来,才算真的会了。
- 挑 3 题预设追问(「那如果数据量再大 10 倍呢?」)并准备答案
参考答案
追问答题模板:先说「结论会不会变」,再说「哪个假设失效了」,最后给替代方案。三个固定方向:数据量大 10 倍、写多读少还建吗、为什么不用别的方案。挑的 3 题选自己最没底的,别挑最顺的。
今日复盘
- 把 D42 的三条优化整理成一份完整案例文档
参考答案
七段结构:背景(库的量级、业务场景,两三句)-> 现象(谁报的、什么症状,量化成超时/耗时数字)-> 定位过程(用了什么工具拿到哪条 SQL,贴 pg_stat_statements 或慢日志的证据)-> 计划对比(优化前后 explain analyze 并排,标出最贵节点怎么消失的)-> 方案(改了什么、为什么)-> 结果数据(前后耗时对比表)-> 反思(重来会怎么做、监控能不能更早发现)。每一段都要有数字,没有数字的段落删掉重写。
- 写出 N+1 的具体现象,并给出 JOIN 或批量查询的改法
参考答案
识别特征比改法更重要:应用日志里同一模板的语句海量出现,基本就是 N+1。ORM 懒加载是重灾区,列表场景必须显式预取。
-- 现象:后端先取 100 个订单,再循环逐个查用户 = 101 次往返 -- 日志特征:同一语句模板几毫秒内刷屏 100 次 -- 改法一:join 一次取回 select o.id, o.total_amount, u.name as 用户名 from orders o join users u on u.id = o.user_id where o.status = 2 order by o.created_at desc limit 100; -- 改法二:数组参数批量取(ORM 里就是预取) select id, name from users where id = any((select array_agg(user_id) from (select user_id from orders where status = 2 order by created_at desc limit 100) t)); - 五步法:定位 -> 分析 -> 假设 -> 验证 -> 回归
易错点
跳过「分析」直接加索引是玄学优化:碰巧好了也不知道为什么,下次照样抓瞎。