优化实战:救活三条慢查询

交付日:从 pg_stat_statements 里挑出最慢的三条,把它们救活,写成可以进简历的案例。

学 10 min
练 85 min
盘 25 min
共 120 分钟

学 · 10 min

  1. 01优化前先记录基线:耗时、执行计划、返回行数--没有基线,优化后说不出「快了多少倍」

练 · 85 min

  1. 从 pg_stat_statements 挑出 3 条秒级查询作为目标
    参考答案

    优先挑「总耗时高 + 平均耗时秒级」的:总耗时高说明它真的在吃数据库,优化它收益最大。没跑过几条查询榜单是空的,先把本周的练习各跑几遍。

    -- 前提:D41 已装好 pg_stat_statements(preload + 重启 + create extension)
    select calls,
           round(total_exec_time::numeric, 0) as 总ms,
           round(mean_exec_time::numeric, 1)  as 平均ms,
           rows,
           left(query, 70) as query
    from pg_stat_statements
    where mean_exec_time >= 1000        -- 平均耗时 ≥1 秒才算「秒级」
    order by total_exec_time desc
    limit 10;
  2. 逐条记录优化前的 EXPLAIN ANALYZE 和耗时
    参考答案

    基线三件套一个都不能少:耗时(\timing / Execution Time)、执行计划、返回行数--没有基线,优化完说不出「快了多少倍」,这是本日铁律,也是过纲里「简历素材」的数字来源。

    \timing on
    
    -- 例:近 30 天日报(换成你自己挑的目标查询)
    explain (analyze, buffers)
    select created_at::date as 日期, count(*) as 单数, sum(total_amount) as gmv
    from orders
    where created_at >= current_date - 30
    group by 1;
  3. 提出假设 -> 加索引或改写 SQL -> 验证
    参考答案

    方法论:一次只改一个变量(只加一个索引或只改一处写法),改完立刻重新 explain--同时动两处就说不清是哪个手段起的作用。假设不成立就回滚(drop index / 还原 SQL),再提下一个假设。

    -- 假设示例 A:「某用户的某时间段」没索引 -> 建复合索引(等值在前、范围在后)
    create index idx_orders_uid_created on orders (user_id, created_at);
    
    -- 假设示例 B:where date(created_at) = ... 函数包列失效 -> 改左闭右开范围
    
    -- 验证:同一个查询重跑
    explain (analyze, buffers)
    select * from orders
    where user_id = '00000000-0000-0000-0000-000000000042'
      and created_at >= current_date - 30;
  4. 记录优化后的计划与耗时,算出提升倍数
    参考答案

    提升倍数 = 优化前耗时 ÷ 优化后耗时,用 Execution Time 算,别用 cost(它不是秒)。注意缓存影响:第一次可能带冷读,多跑两三次取稳定值再记录。

    \timing on
    
    -- 与基线一模一样的查询再跑一次
    explain (analyze, buffers)
    select created_at::date as 日期, count(*) as 单数, sum(total_amount) as gmv
    from orders
    where created_at >= current_date - 30
    group by 1;
  5. 整理成对比表格:查询 | 优化前 | 优化后 | 手段 | 提升倍数
    参考答案

    表格列就用题面那五列:查询 | 优化前 | 优化后 | 手段 | 提升倍数。示例一行:「近 30 天日报 | ≈1s | ≈100ms | created_at 加索引 | ≈10×」。每行都要能附上优化前后的执行计划--面试官追问「为什么快了」,拿计划说话,不拿感觉说话。

过关标准 三条查询都有明确提升倍数,且能解释每一条为什么快了。这是简历上可以直接写的东西。