GP-SQL優化之explain analyze

通過explain觀察執行計劃,從而確定如何優化SQL

查詢優化器使用數據庫的數據統計信息來選擇具有最小總代價的查詢計劃,查詢代價通過磁盤I/O取得的磁盤頁面數作爲單位來度量。 可以使用EXPLAIN和EXPLAIN ANALYZE語句發現和改進查詢計劃。

EXPLAIN的語法如下:

1EXPLAIN [ ANALYZE ] [ VERBOSE ] statement
  • ANALYZE:執行命令並顯示實際運行時間。
  • VERBOSE:顯示規劃樹完整的內部表現形式,而不僅是一個摘要。通常,這個選項只是在特殊的調試過程中有用。VERBOSE輸出是否打印工整的,具體取決於配置參數 explain_pretty_print 的值。
  • statement:查詢執行計劃的 SQL 語句,可以是任何
    select、insert、update、delete、values、execute、declare 語句。

EXPLAIN展示查詢優化器對該查詢計劃估計的代價,但是不執行該查詢。例如:

EXPLAIN SELECT * FROM test WHERE id=2; 

在這裏插入圖片描述
EXPLAIN ANALYZE不僅會顯示查詢計劃,還會實際運行語句。EXPLAIN ANALYZE會丟掉任何來自SELECT語句的輸出,但是該語句中的其他操作會被執行(例如INSERT、UPDATE或者DELETE)。要在DML語句上使用EXPLAIN ANALYZE卻不讓該命令影響數據,可以明確地把EXPLAIN ANALYZE用在一個事務中:

BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;)。

EXPLAIN ANALYZE運行語句後除了顯示計劃外,還有下列額外的信息:

1、運行該查詢消耗的總時間(以毫秒計) 計劃節點操作中涉及的工作者(Segment)數量
2、操作中產生最多行的Segment返回的最大行數(及其Segment ID) 操作所使用的內存
3、從產生最多行的Segment中檢索到第一行所需的時間(以毫秒計),以及從該Segment中檢索所有行花費的總時間。

例如:

EXPLAIN ANALYZE SELECT * FROM test WHERE id=2;

在這裏插入圖片描述
閱讀EXPLAIN輸出

查詢計劃類似於一棵有節點的樹,執行和閱讀的順序是自底而上。計劃中的每個節點表示一個操作,例如表掃描、表連接、聚集或者排序。閱讀的順序是從底向上:每個節點會把結果輸出給直接在它上面的節點。一個計劃中的底層節點通常是表掃描操作:順序掃描表、通過索引或者位圖索引掃描表等。如果該查詢要求那些行上的連接、聚集、排序或者其他操作,就會有額外的節點在掃描節點上面負責執行這些操作。最頂層的計劃節點通常是數據庫的移動(MOTION)節點:重分佈(REDISTRIBUTE)、廣播(BROADCAST)或者收集(GATHER)節點。這些操作在查詢處理時在實例節點之間移動數據。

EXPLAIN的輸出對於查詢計劃中的每個節點都顯示爲一行並顯示該節點類型和下面的執行的代價估計:

  • cost:以磁盤頁面獲取爲單位度量。1.0等於一次順序磁盤頁面讀取。第一個估計是得到第一行的啓動代價,第二個估計是得到所有行的總代價。
  • rows:這個計劃節點輸出的總行數。這個數字根據條件的過濾因子會小於被該計劃節點處理或者掃描的行數。最頂層節點的是估算的返回、更新或者刪除的行數。
  • width:這個計劃節點輸出的所有行的總字節數。

需要注意以下兩點:

  • 一個節點的代價包括其子節點的代價。最頂層計劃節點有對於該計劃估計的總執行代價。這是優化器估算出來的最小的數字。
  • 代價只反映了在數據庫中執行的時間,並沒有計算在數據庫執行之外的時間,例如將結果行傳送到客戶端花費的時間。
    rows:根據統計信息估計SQL返回結果集的行數
    width:返回的結果集的每一行的長度,這個長度值是根據pg_statistic表中的統計信息來計算的。

EXPLAIN舉例

下面的例子描述瞭如何閱讀一個查詢的EXPLAIN查詢代價:

EXPLAIN SELECT * FROM names WHERE name = 'Joelle';
                 						QUERY PLAN

--------------------------Gather Motion 4:1 (slice1) (cost=0.00…20.88 rows=1 width=13)
-> Seq Scan on ‘names’ (cost=0.00…20.88 rows=1 width=13)
Filter: name::text ~~ ‘Joelle’::text

查詢優化器會順序掃描names表,對每一行檢查WHERE語句中的filter條件,只輸出滿足該條件的行。 掃描操作的結果被傳遞給一個Gather Motion操作。Gather Motion是Segment把所有行發送給Master節點。在這個例子中,有4個Segment節點會並行執行,並向Master節點發送數據。這個計劃估計的啓動代價是00.00(沒有代價)而總代價是20.88次磁盤頁面獲取。優化器估計這個查詢將返回一行數據。

EXPLAIN ANALYZE除了顯示執行計劃還會運行語句。EXPLAIN ANALYZE計劃會把實際執行代價和優化器的估計一起顯示,同時顯示額外的下列信息:

  • 查詢執行的總運行時間(以毫秒爲單位)。
  • 查詢計劃每個Slice使用的內存,以及爲整個查詢語句保留的內存。
  • 計劃節點操作中涉及的Segment節點數量,其中只會統計返回行的Segment。
  • 操作產生最多行的Segment節點返回的行最大數量。如果多個Segment節點產生了相等的行數,EXPLAIN ANALYZE會顯示那個用了最長結束時間的Segment節點。
  • 爲一個操作產生最多行的Segment節點的ID。
  • 相關操作使用的內存量(work_mem)。如果work_mem不足以在內存中執行該操作,計劃會顯示溢出到磁盤的數據量最少的Segment的溢出數據量。

例如:

Work_mem used: 64K bytes avg, 64K bytes max (seg0). Work_mem wanted:
90K bytes avg, 90K byes max (seg0) to lessen workfile I/O affecting 2
workers.

產生最多行的Segment節點檢索到第一行的時間(以毫秒爲單位)以及該Segment節點檢索到所有行花掉的時間。
下面的例子用同一個查詢描述瞭如何閱讀一個EXPLAIN ANALYZE查詢計劃。這個計劃中粗體部分展示了每一個計劃節點的實際計時和返回行,以及整個查詢的內存和時間統計信息。

EXPLAIN ANALYZE SELECT * FROM names WHERE name = 'Joelle';
               						  QUERY PLAN

------------------------------------------------------------ Gather Motion 2:1 (slice1; segments: 2) (cost=0.00…20.88 rows=1 width=13)
Rows out: 1 rows at destination with 0.305 ms to first row, 0.537 ms
to end, start offset by 0.289 ms.
-> Seq Scan on names (cost=0.00…20.88 rows=1 width=13) Rows out: Avg 1 rows x 2 workers. Max 1 rows (seg0) with 0.255 ms to first
row, 0.486 ms to end, start offset by 0.968 ms.
Filter: name = ‘Joelle’::text Slice statistics:
(slice0) Executor memory: 135K bytes.
(slice1) Executor memory: 151K bytes avg x 2 workers, 151K bytes max (seg0).

Statement statistics: Memory used: 128000K bytes Total runtime: 22.548
ms

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章