EXPLAIN

Name

EXPLAIN -- 顯示語句執行規劃

Synopsis

EXPLAIN [ ANALYZE ] [ VERBOSE ] statement

描述

這條命令顯示PostgreSQL規劃器為所提供的語句生成的執行規劃。 執行規劃顯示語句引用的資料表是如何被掃瞄的 — 是簡單的順序掃瞄,還是索引掃瞄等 — 並且如果引用了多個資料表, 採用了什麼樣的連接算法從每個輸入的資料表中取出所需要的記錄。

顯示出來的最關鍵的部分是預計的語句執行開銷, 這就是規劃器對執行該語句所需時間的估計(以磁盤頁面存取為單位計量)。 實際上顯示了兩個數字:返回第一行記錄前的啟動時間, 和返回所有記錄的總時間。對於大多數查詢而言,關心的是總時間,但是, 在某些環境下,比如一個 EXISTS 子查詢裡, 規劃器將選擇最小啟動時間而不是最小總時間(因為執行器在獲取一條記錄後總是要停下來)。 同樣,如果您用一條 LIMIT 子句限制返回的記錄數, 規劃器會在最終的開銷上做一個合理的插值以計算哪個規劃開銷最省。

ANALYZE 選項導致查詢被實際執行,而不僅僅是規劃。 它在顯示中增加了在每個規劃節點內部花掉的總時間(以毫秒計)和它實際返回的行數。 這些資料對搜索該規劃器的預期是否和現實相近很有幫助。

Important: 要記住的是查詢實際上在使用 ANALYZE 的時候是執行的。 儘管 EXPLAIN 會拋棄任何 SELECT 會返回的輸出, 但是其它查詢的副作用還是一樣會發生的。 如果您在 INSERTUPDATEDELETE,或者 EXECUTE 語句裡使用 EXPLAIN ANALYZE,而且還不想讓查詢影響您的資料, 用下面的方法:

BEGIN;
EXPLAIN ANALYZE ...;
ROLLBACK;

參數

ANALYZE

執行命令並顯示實際執行時間。

VERBOSE

顯示規劃樹完整的內部資料表現形式,而不僅僅是一個摘要。 通常,這個選項只是在特殊的調試過程的時候有用。 VERBOSE 輸出可能是打印得工整的,也可能不是, 具體取決於配置參數 explain_pretty_print

語句

任何SELECTINSERTUPDATEDELETEEXECUTE,或者 DECLARE 語句。

注意

PostgreSQL 裡只有很少的一些文件介紹有關優化器計算開銷的問題。 參考 Section 13.1 獲取更多訊息。

為了讓 PostgreSQL 查詢規劃器在優化查詢的時候做出合理的判斷, 我們需要執行 ANALYZE 語句以記錄有關資料在資料表中的分佈的統計訊息。 如果您沒做過這件事情(或者如果自上次 ANALYZE 以來, 資料表中的資料統計分佈發生了顯著變化),那麼計算出來的開銷預計很可能與查詢的實際屬性並不對應, 因此很可能會選取一個比較差的查詢規劃。

PostgreSQL 7.3 以前,查詢規劃是以 NOTICE 消息的形式發出來的。 現在它的顯示格式是一個查詢結果(格式化成了類似一個有單個文本字串的資料表。)

例子

顯示一個對只有一個 int4 列和 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 < 4;

                             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.66..0.67 rows=7 loops=1)
   ->  Index Scan using test_pkey on test  (cost=0.00..32.97 rows=1311 width=8) (actual time=0.05..0.39 rows=99 loops=1)
         Index Cond: ((id > $1) AND (id < $2))
 Total runtime: 0.85 msec
(4 rows)
   

注意這裡顯示的數字, 甚至還有選擇的查詢策略都有可能在各個 PostgreSQL版本之間不同--因為規劃器在不斷改進。 另外,ANALYZE 命令使用隨機的採樣來估計資料統計; 因此,一次新的 ANALYZE 執行之後開銷估計可能會變化, 即使資料的實際分佈沒有改變也這樣。

相容性

在 SQL 標準中沒有EXPLAIN 語句。

又見

ANALYZE