PostgreSQL执行计划
pg的执行计划和MySQL的执行计划的显示有一点不一样,我得补习一下。
1. 基本命令:EXPLAIN
EXPLAIN
命令会显示 PostgreSQL 规划器为给定的 SQL 语句生成的执行计划。它不会实际执行该语句,只是预测其执行路径和成本。
语法:
sql
EXPLAIN your_sql_statement;
示例:
sql
EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';
输出内容解读:
输出是一个树形结构,一般是从下向上看执行步骤,只需要关注下面几点:
-
操作类型 (Node Type) :表示执行的操作,如
Seq Scan
(顺序扫描)、Index Scan
(索引扫描)、Hash Join
(哈希连接)、Sort
(排序)等。 -
关联关系 (Relationship) :显示表之间的关联方式,如
INNER
或LEFT
。 -
成本 (Cost) :包含两个数字,例如
(cost=0.00..15.03 rows=1 width=44)
。0.00
:启动成本,即获取第一行数据的预估成本。15.03
:总成本,即获取所有行数据的预估成本。rows=1
:预估返回的行数。width=44
:预估每行数据的平均宽度(字节)。
-
实际数据 (Actual) :如果你使用
EXPLAIN ANALYZE
,这里会显示实际执行的数据。
2. 关键命令:EXPLAIN ANALYZE
这是最常用且最强大的组合。EXPLAIN ANALYZE
会实际执行 SQL 语句,并返回真实的执行计划和实际的执行统计信息(如时间、返回行数)。
语法:
sql
EXPLAIN ANALYZE your_sql_statement;
示例:
sql
EXPLAIN ANALYZE SELECT * FROM orders WHERE user_id = 123 AND status = 'shipped';
输出内容解读:
除了 EXPLAIN
的信息外,还会增加:
-
实际时间 (Actual Time) :例如
(actual time=0.018..0.019 rows=1 loops=1)
。0.018
:获取第一行实际花费的时间(毫秒)。0.019
:获取所有行实际花费的时间(毫秒)。rows=1
:实际返回的行数。loops=1
:该节点执行的次数。
-
执行时间 :计划末尾的
Execution Time
显示了整个查询的实际总耗时。
⚠️ 重要警告 :
对于 INSERT
, UPDATE
, DELETE
, CREATE TABLE AS
等会修改数据的语句,EXPLAIN ANALYZE
会真的执行这些操作!在生产环境中使用前,请务必在测试环境确认,或者将其包裹在一个事务中并回滚:
sql
BEGIN;
EXPLAIN ANALYZE UPDATE table_name SET column = value WHERE condition;
ROLLBACK; -- 分析完成后回滚,不会真正修改数据
3. 如何解读和分析执行计划
查看执行计划的目的是找到性能瓶颈。以下是一些常见的需要关注的性能红灯:
-
全表扫描 (Seq Scan) :
- 对大数据表进行全表扫描通常性能很差。检查是否可以为
WHERE
子句中的条件字段创建索引。
- 对大数据表进行全表扫描通常性能很差。检查是否可以为
-
昂贵的操作 :
- Sort: 昂贵的排序操作,尤其是在处理大量数据时。考虑是否可以通过索引来避免排序。
- Hash Join / Hash Aggregate: 这些操作需要在内存中构建哈希表,如果数据量大,可能会占用大量内存甚至使用磁盘临时文件,导致变慢。
- Nested Loop: 如果内循环的数据集很大,性能会非常差。
总结步骤
-
找到慢查询:通过日志查询。
-
使用
EXPLAIN ANALYZE
:在测试环境中运行它来获取真实的执行计划。 -
寻找瓶颈:从上到下阅读执行计划,寻找全表扫描、不准确的预估、昂贵的排序或哈希操作。
-
提出优化方案:
- 增加索引 (最常用):为
WHERE
,JOIN
,ORDER BY
,GROUP BY
子句中的字段添加索引。 - 优化查询 :重写查询,避免不必要的操作(如
SELECT *
,复杂的子查询)。
- 增加索引 (最常用):为