?
This document uses PHP Chinese website manual Release
EXPLAIN [ ( option [, ...] ) ] statement
EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
where option can be one of:
ANALYZE [ boolean ]
VERBOSE [ boolean ]
COSTS [ boolean ]
BUFFERS [ boolean ]
FORMAT { TEXT | XML | JSON | YAML }
這條命令顯示PostgreSQL規(guī)劃器為所提供的語句生成的執(zhí)行規(guī)劃。 執(zhí)行規(guī)劃顯示語句引用的表是如何被掃描的(簡單的順序掃描,還是索掃描),并且如果引用了多 個表,采用了什么樣的連接算法從每個輸入的表中取出所需要的記錄。
顯示出來的最關(guān)鍵的部分是預(yù)計(jì)的語句執(zhí)行開銷,這就是規(guī)劃器對運(yùn)行該語句所需時(shí)間的估計(jì) (以磁盤頁面存取為單位計(jì)量)。實(shí)際上顯示了兩個數(shù)字:返回第一行記錄前的啟動時(shí)間,和返 回所有記錄的總時(shí)間。對于大多數(shù)查詢而言,關(guān)心的是總時(shí)間,但是,在某些環(huán)境下, 比如一個EXISTS子查詢里,規(guī)劃器將選擇最小啟動時(shí)間而不是最小總時(shí)間 (因?yàn)閳?zhí)行器在獲取一條記錄后總是要停下來)。同樣,如果你用一條LIMIT 子句限制返回的記錄數(shù),規(guī)劃器會在最終的開銷上做一個合理的插值以計(jì)算哪個規(guī)劃開銷最省。
ANALYZE選項(xiàng)導(dǎo)致查詢被實(shí)際執(zhí)行,而不僅僅是規(guī)劃。它在顯示中增加了 在每個規(guī)劃節(jié)點(diǎn)內(nèi)部花掉的總時(shí)間(以毫秒計(jì))和它實(shí)際返回的行數(shù)。 這些數(shù)據(jù)對搜索該規(guī)劃器的預(yù)期是否和現(xiàn)實(shí)相近很有幫助。
Important: 要記住的是查詢實(shí)際上在使用ANALYZE的時(shí)候是執(zhí)行的。 盡管EXPLAIN會拋棄任何SELECT返回的輸出, 但是其它查詢的副作用還是一樣會發(fā)生的。 如果你在INSERT,UPDATE, DELETE,CREATE TABLE AS, 或EXECUTE語句里使用EXPLAIN ANALYZE而且 還不想讓查詢影響數(shù)據(jù), 可以用下面的方法:
BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;
只有ANALYZE和VERBOSE選項(xiàng)可以被指定, 并且僅僅按那個順序,不把該選項(xiàng)列在括號內(nèi)。在PostgreSQL9.0 之前,該unparenthesized語法是唯一支持的。希望所有的新選項(xiàng)僅僅在parenthesized 語法中支持。
執(zhí)行命令并顯示實(shí)際運(yùn)行時(shí)間,此參數(shù)缺省FALSE。
顯示關(guān)于計(jì)劃的附加信息。尤其,包括計(jì)劃樹中的每個節(jié)點(diǎn)的輸出列列表,模式修飾的表 和函數(shù)名稱,總是有射程表別名的表達(dá)式的標(biāo)號變量,并且總是輸出顯示統(tǒng)計(jì)的每個觸發(fā) 器的名稱。該參數(shù)默認(rèn)為FALSE。
包括預(yù)計(jì)啟動項(xiàng)上的信息和每個計(jì)劃節(jié)點(diǎn)的總成本,以及估計(jì)行數(shù)和估計(jì)的每行的寬度。 該參數(shù)默認(rèn)為TRUE。
包含關(guān)于緩沖區(qū)使用的信息。尤其,包括共享塊觸發(fā)、讀和寫的數(shù)量,本地塊觸發(fā)、讀 和寫的數(shù)量,以及臨時(shí)快讀和寫的數(shù)量。共享塊、本地塊和臨時(shí)塊分別包含表和索引,臨時(shí) 表和臨時(shí)索引,以及在排序和物化計(jì)劃中使用的磁盤塊。為上層節(jié)點(diǎn)顯示的塊數(shù)包括 所有其子節(jié)點(diǎn)使用的塊數(shù)。該參數(shù)僅可能與ANALYZE參數(shù)一起使用。 它默認(rèn)為FALSE。
指定輸出格式,輸出格式可以是 TEXT, XML, JSON,或者YAML。非文本輸出包含與文本輸出 格式相同的信息,但更容易對程序解析。該參數(shù)默認(rèn)為TEXT。
指定選中的選項(xiàng)是該開啟還是關(guān)閉。你可以寫TRUE, ON, 或者1來啟動該選項(xiàng),并且用FALSE, OFF, 或者0來關(guān)閉它。 boolean 值也可以被忽略, 此時(shí)假定為 TRUE。
你想要查看規(guī)劃結(jié)果的任何SELECT,INSERT,UPDATE, DELETE,VALUES,EXECUTE, DECLARE或CREATE TABLE AS語句之一。
在PostgreSQL里只有很少的一些文檔介紹有關(guān)優(yōu)化器計(jì)算開銷的問題。 參考Section 14.1獲取更多信息。
為了讓PostgreSQL查詢規(guī)劃器在優(yōu)化查詢的時(shí)候做出合理的判斷, 需要運(yùn)行ANALYZE語句以記錄有關(guān)數(shù)據(jù)在表中的分布的統(tǒng)計(jì)信息。 如果你沒做過這件事情(或者如果自上次ANALYZE以來,表中的數(shù)據(jù)統(tǒng)計(jì)分 布發(fā)生了顯著變化), 那么計(jì)算出來的開銷預(yù)計(jì)很可能與查詢的實(shí)際屬性并不對應(yīng), 因此很可能會選取一個比較差勁的查詢規(guī)劃。
為了測量在執(zhí)行計(jì)劃中的每個節(jié)點(diǎn)的運(yùn)行時(shí)間成本,EXPLAIN ANALYZE 的當(dāng)前實(shí)現(xiàn)可以添加大量剖析開銷來查詢執(zhí)行。因此,在一個查詢中運(yùn)行 EXPLAIN ANALYZE有時(shí)會花費(fèi)比常規(guī)執(zhí)行查詢的時(shí)間明顯更長的時(shí)間。 開銷的數(shù)量依賴于查詢的性質(zhì)。
顯示一個對只有一個integer列和10000行表的簡單查詢的查詢規(guī)劃:
EXPLAIN SELECT * FROM foo; QUERY PLAN --------------------------------------------------------- Seq Scan on foo (cost=0.00..155.00 rows=10000 width=4) (1 row)
Here is the same query, with JSON formatting:
EXPLAIN (FORMAT JSON) SELECT * FROM foo; QUERY PLAN -------------------------------- [ + { + "Plan": { + "Node Type": "Seq Scan",+ "Relation Name": "foo", + "Alias": "foo", + "Startup Cost": 0.00, + "Total Cost": 155.00, + "Plan Rows": 10000, + "Plan Width": 4 + } + } + ] (1 row)
如果存在一個索引,并且使用一個可應(yīng)用索引的WHERE條件的查詢, EXPLAIN會顯示不同的規(guī)劃:
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)
Here is the same query, but in YAML output:
EXPLAIN (FORMAT YAML) SELECT * FROM foo WHERE i='4'; QUERY PLAN ------------------------------- - Plan: + Node Type: "Index Scan" + Scan Direction: "Forward"+ Index Name: "fi" + Relation Name: "foo" + Alias: "foo" + Startup Cost: 0.00 + Total Cost: 5.98 + Plan Rows: 1 + Plan Width: 4 + Index Cond: "(i = 4)" (1 row)
XML輸出時(shí)留給讀者作為練習(xí)的。
這是成本抑制的相同計(jì)劃:
EXPLAIN (COSTS FALSE) SELECT * FROM foo WHERE i = 4; QUERY PLAN ---------------------------- Index Scan using fi on foo Index Cond: (i = 4) (2 rows)
下面是一個使用了聚集函數(shù)的查詢的查詢規(guī)劃:
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顯示一個已預(yù)編寫的查詢規(guī)劃的例子:
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)
注意這里顯示的數(shù)字,甚至還有選擇的查詢策略都有可能在各個 PostgreSQL版本之間不同,因?yàn)橐?guī)劃器在不斷改進(jìn)。 另外,ANALYZE命令使用隨機(jī)的采樣來估計(jì)數(shù)據(jù)統(tǒng)計(jì);因此, 一次新的ANALYZE運(yùn)行之后開銷估計(jì)可能會變化,即使數(shù)據(jù)的 實(shí)際分布沒有改變也這樣。
在SQL標(biāo)準(zhǔn)中沒有EXPLAIN語句。