SQL 性能优化
针对这条查询,不要通用建议
你是数据库专家。这条 SQL 在 [表名,约 X 万行] 上执行需要 [耗时]。请:1)指出最可能的瓶颈(看执行计划);2)给出优化后的 SQL;3)说明需要加什么索引,以及加了之后可能的副作用(写入变慢/空间占用)。不要给我「避免 SELECT *」这类通用建议。 ```sql [粘贴 SQL] ```
适合什么场景
- 单次查询超过 SLA(比如 2 秒),表在百万行级,手里有 EXPLAIN 输出。
- 上线前 review 一条会跑在报表或定时任务里的重查询。
不适合的场景
- 表只有几千行、查询 30 毫秒:优化收益为负,先别动。
- 慢的原因是锁等待或连接池耗尽,不是 SQL 本身:先看 pg_stat_activity 和慢日志。
示例
输入
SELECT o.id, o.created_at, u.email
FROM orders o
JOIN users u ON u.id = o.user_id
WHERE date_trunc('day', o.created_at) = '2026-03-01'
ORDER BY o.created_at DESC
LIMIT 50;
-- orders 约 800 万行,执行 6.4 秒
-- EXPLAIN 显示 Seq Scan on orders你会得到
指出 date_trunc 让 created_at 上的索引失效,条件应改成 `>= '2026-03-01' AND < '2026-03-02'`;其次是 ORDER BY 走不到索引,需要 (created_at DESC) 或 (created_at, user_id) 索引,并说明写入变慢的代价。改写后应看到 Seq Scan 变成 Index Scan,耗时降到百毫秒级。
常见误用
- 只给 SQL,不给执行计划和耗时:它只能按语法猜瓶颈。
- 让它「优化一下」,它可能把 LEFT JOIN 改成 INNER JOIN,结果行数变了却不提醒。
可以这样改
- 贴上 `EXPLAIN (ANALYZE, BUFFERS)` 原文,瓶颈判断从猜变成读数。
- 加「先给三种改法及各自取舍,我再选」,避免它默认选最激进的重写。