EXPLAIN
EXPLAIN — 显示一条语句的执行计划
大纲
EXPLAIN [ ANALYZE ] [ VERBOSE ] statement描述
这条命令显示PostgreSQL规划器为给定语句生成的执行计划。执行计划显示语句引用的表将被如何扫描——用普通的顺序扫描、索引扫描等——以及当引用多个表时,将使用什么连接算法把每个输入表中所需的行汇集到一起。
显示中最关键的部分是估计的语句执行代价,即规划器对运行该语句所需时间的猜测(以磁盘页获取次数为单位度量)。实际上会显示两个数字:返回第一行之前的启动时间,以及返回所有行的总时间。对大多数查询来说,总时间才是重要的,但在诸如
EXISTS中的子查询这样的上下文中,规划器会选择最小的启动时间而不是最小的总时间(因为执行器在取到一行后无论如何都会停止)。另外,如果你用LIMIT子句限制返回的行数,规划器会在端点代价之间做适当的插值,来估计哪个计划实际上最便宜。
ANALYZE选项使语句被真正执行,而不仅仅是规划。每个计划节点内部花费的总耗时(毫秒)以及它实际返回的总行数会被添加到显示中。这对于查看规划器的估计是否接近现实很有用。
重要
请记住,使用ANALYZE时语句会被真正执行。虽然EXPLAIN会丢弃SELECT
本会返回的任何输出,但语句的其他副作用会照常发生。如果你想在INSERT、UPDATE、DELETE或EXECUTE语句上使用
EXPLAIN ANALYZE而又不让命令影响你的数据,可以使用这样的方法:
BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;
参数
ANALYZE执行命令并显示实际的运行时间。
VERBOSE显示计划树的完整内部表示,而不仅仅是一个摘要。通常这个选项只对调试PostgreSQL有用。
VERBOSE输出是否美化打印取决于explain_pretty_print配置参数的设置。statement任何你希望看到其执行计划的
SELECT、INSERT、UPDATE、DELETE、EXECUTE或DECLARE语句。
注解
关于优化器在PostgreSQL中对代价信息的使用,目前只有很少的文档。更多信息请参阅第 13.1 节。
为了让PostgreSQL查询规划器在优化查询时能做出充分知情的决定,应当运行ANALYZE
语句来记录表中数据分布的统计信息。如果你没有这样做(或者自上次运行ANALYZE以来表中数据的统计分布发生了显著变化),估计的代价不太可能符合查询的真实特性,因此可能选择一个较差的查询计划。
在PostgreSQL 7.3 之前,计划以
NOTICE消息的形式发出。现在它作为查询结果出现(格式化为一个只有单个文本列的表)。
示例
要显示对一个只有单个integer列和 10000 行的表的简单查询的计划:
EXPLAIN SELECT * FROM foo;
QUERY PLAN
---------------------------------------------------------
Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4)
(1 row)
如果有一个索引,并且我们的查询带有可索引的WHERE
条件,EXPLAIN可能会显示一个不同的计划:
EXPLAIN SELECT * FROM foo WHERE i = 4;
QUERY PLAN
--------------------------------------------------------------
Index Scan using fi on foo (cost=0.00..5.98 rows=1 width=4)
Index Cond: (i = 4)
(2 rows)
下面是一个使用聚合函数的查询的查询计划示例:
EXPLAIN SELECT sum(i) FROM foo WHERE i < 10;
QUERY PLAN
---------------------------------------------------------------------
Aggregate (cost=23.93..23.93 rows=1 width=4)
-> Index Scan using fi on foo (cost=0.00..23.92 rows=6 width=4)
Index Cond: (i < 10)
(3 rows)
下面是使用EXPLAIN EXECUTE显示一个预备查询的执行计划的例子:
PREPARE query(int, int) AS SELECT sum(bar) FROM test
WHERE id > $1 AND id < $2
GROUP BY foo;
EXPLAIN ANALYZE EXECUTE query(100, 200);
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
HashAggregate (cost=39.53..39.53 rows=1 width=8) (actual time=0.661..0.672 rows=7 loops=1)
-> Index Scan using test_pkey on test (cost=0.00..32.97 rows=1311 width=8) (actual time=0.050..0.395 rows=99 loops=1)
Index Cond: ((id > $1) AND (id < $2))
Total runtime: 0.851 ms
(4 rows)
当然,这里显示的具体数字取决于所涉及表的实际内容。还要注意,由于规划器的改进,这些数字、甚至被选中的查询策略都可能随
PostgreSQL版本而变化。此外,ANALYZE命令使用随机抽样来估计数据统计;因此,即使表中数据的实际分布没有变化,在重新运行一次
ANALYZE之后,代价估计也有可能改变。
兼容性
SQL 标准中没有定义EXPLAIN语句。