大促收官:写一份优化案例文档

大促平稳收官。你把 W6–W7 的优化经历写成文档--这将是简历上最硬的一条。

学 0 min
练 90 min
盘 30 min
共 120 分钟

文档结构

  1. 01背景 -> 现象 -> 定位过程 -> 计划对比 -> 方案 -> 结果数据 -> 反思

  2. 02关键:每一步都要有数字和证据

练 · 120 min

  1. 把 D42 的三条优化整理成一份完整案例文档
    参考答案

    七段结构:背景(库的量级、业务场景,两三句)-> 现象(谁报的、什么症状,量化成超时/耗时数字)-> 定位过程(用了什么工具拿到哪条 SQL,贴 pg_stat_statements 或慢日志的证据)-> 计划对比(优化前后 explain analyze 并排,标出最贵节点怎么消失的)-> 方案(改了什么、为什么)-> 结果数据(前后耗时对比表)-> 反思(重来会怎么做、监控能不能更早发现)。每一段都要有数字,没有数字的段落删掉重写。

  2. 贴上优化前后的执行计划截图或文本
    参考答案

    贴 explain analyze 的文本原文即可(截图也行):优化前的计划标出耗时最大的节点、rows 估算与 actual 的偏差;优化后贴同一条查询的计划,用箭头标出变化(如 Seq Scan -> Index Scan、扫描行数从百万降到 20)。前后并排是关键,单独一张计划说服力减半。

  3. 写出「为什么这个方案,而不是另一个方案」的取舍
    参考答案

    取舍段写法:列至少两个候选方案、各自的代价、一句结论。例:深分页选 keyset 而不是延迟关联,因为后台只有上一页/下一页的场景、keyset 耗时恒定;仪表盘选物化视图而不是优化原查询,因为业务容忍分钟级延迟、而实时优化要动五张表的 join。没有取舍过程的文档 = 没做过选择题,面试官一眼看穿。

  4. 写一段 3 分钟的口头版本,录音听一遍
    参考答案

    口头版结构:一句话现象 -> 定位用了哪两步 -> 方案一句话 -> 结果数字(从 X 到 Y)-> 一句反思。对着手机录 3 分钟再回放:卡壳的地方就是还没想透的地方,回文档补上;第二遍脱稿讲,不许念稿。

  5. 提炼成简历上的一句话(带数字)
    参考答案

    简历句式:「用 A 手段把 B 指标从 X 做到 Y」。例:定位并修复后台深分页慢查询,列表接口 P99 从 8s 降到 50ms(keyset 分页 + 延迟关联);或:为百万订单表设计按月分区归档方案,历史查询扫描量降 90%。X/Y 必须是文档里真实测过的数字--面试官一定会追问这个数字怎么来的。

过关标准 文档能独立看懂;口头版本 3 分钟内讲完且每句都经得起追问。

今日复盘

  1. 用唯一索引 + ON CONFLICT DO NOTHING 实现幂等下单
    参考答案

    只有第一次 returning 返回 id(= 抢到),之后每次都返回 0 行=重复请求在数据库层被无声吞掉。幂等键的颗粒度是业务定的:用户+活动还是用户+商品,想清楚再建。

    -- 秒杀订单表:幂等键 = (user_id, activity_id),一人一单
    create table seckill_orders (
      id          bigint generated always as identity primary key,
      user_id     uuid not null,
      activity_id int  not null,
      created_at  timestamp not null default now(),
      unique (user_id, activity_id)
    );
    
    -- 同一用户连点五次 = 同一条语句发五遍,连跑五遍看效果
    insert into seckill_orders (user_id, activity_id)
    values ('00000000-0000-0000-0000-000000000042', 1)
    on conflict (user_id, activity_id) do nothing
    returning id;
    
    select * from seckill_orders;   -- 无论跑几遍,永远只有一行
  2. 把 D13 的月报查询建成普通视图
    参考答案

    视图只是把一条查询存了起来:对它 select 每次都重新聚合百万行,\timing 一开就能感受到。它的价值是封装和权限边界,不是提速。

    create view v_monthly as
    select date_trunc('month', created_at) as 月份,
           count(*) as 单数,
           sum(total_amount) as gmv
    from orders
    group by 1;
    
    select * from v_monthly order by 月份;
  3. 优化前先记录基线:耗时、执行计划、返回行数--没有基线,优化后说不出「快了多少倍」