GreenPlum--閱讀解釋計劃

如何閱讀解釋計劃

解釋計劃是一份報告,它詳細描述了Greenplum數據庫優化器確定的執行查詢要遵循的步驟。計劃是一棵節點構成的樹,應該從底向上閱讀,每一個節點都會將其結果傳遞給其直接上層節點。每個節點表示計劃中的一個步驟,每個節點對應的那一行標識了在該步驟中執行的操作——例如掃描、連接、聚集或者排序操作。節點還標識了用於執行該操作的方法。例如,掃描操作的方法可能是順序掃描或者索引掃描。而連接操作可以執行哈希連接或者嵌套循環連接。

下面是一個簡單查詢的解釋計劃。該查詢在存儲於每一Segment中的分佈表中查找行數。

gpacmin=# EXPLAIN SELECT gp_segment_id, count(*)
FROM contributions
GROUP BY gp_segment_id;

                             QUERY PLAN 

-------------------------------------------------------------------------------- Gather Motion 2:1 (slice2; segments: 2) (cost=0.00…4.44 rows=4
width=16) -> HashAggregate (cost=0.00…3.38 rows=4 width=16)
Group By: contributions.gp_segment_id
-> Redistribute Motion 2:2 (slice1; segments: 2)
(cost=0.00…2.12 rows=4 width=8)
Hash Key: contributions.gp_segment_id
-> Sequence (cost=0.00…1.09 rows=4 width=8)
-> Result (cost=10.00…100.00 rows=50 width=4)
-> Function Scan on gp_partition_expansion
(cost=10.00…100.00 rows=50 width=4)
-> Dynamic Table Scan on contributions (partIndex: 0)
(cost=0.00…0.03 rows=4 width=8) Settings: optimizer=on (10 rows)

這個計劃有七個節點——Dynamic Table Scan、Function Scan、Result、Sequence、Redistribute Motion、HashAggregate和最後的Gather Motion。每一個節點包含三個代價估計:代價cost(讀取的順序頁面)、行數rows以及行寬度width。

代價cost由兩部分構成。1.0的代價等於一次順序磁盤頁面讀取。估計的第一部分是啓動代價,它是得到第一行的代價。第二個不急是總代價,它是得到所有行的代價。

行數rows估計是由計劃節點輸出的行數。這個數字可能會小於計劃節點實際處理或者掃描的行數,它反映了WHERE子句條件的選擇度估計。總代價假設所有的行將被檢索出來,但並非總是這樣(例如,如果用戶使用LIMIT子句)。

寬度width估計是計劃節點輸出的所有列的以字節計的總寬度。

節點中的代價估計包括了其所有子節點的代價,因此計劃中最頂層節點(通常是一個Gather Motion)具有對計劃總體執行代價的估計。這就是查詢規劃器想要最小化的數字。

掃描操作符掃描表中的行以尋找一個行的集合。對於不同種類的存儲有不同的掃描操作符。它們包括:

對錶上的Seq Scan — 掃描表中的所有行。
Append-only Scan — 掃描行存追加優化表。
Append-only Columnar Scan — 掃描列存追加優化表中的行。
Index Scan — 遍歷一個B-樹索引以從表中取得行。
Bitmap Append-only Row-oriented Scan — 從索引中收集僅追加表中行的指針並且按照磁盤上的位置進行排序。
Dynamic Table Scan — 使用一個分區選擇函數來選擇分區。Function Scan節點包含分區選擇函數的名稱,可以是下列之一:
gp_partition_expansion — 選擇表中的所有分區。不會有分區被消除。
gp_partition_selection — 基於一個等值表達式選擇一個分區。
gp_partition_inversion — 基於一個範圍表達式選擇分區。
Function Scan節點將動態選擇的分區列表傳遞給Result節點,該節點又會被傳遞給Sequence節點。

Join操作符包括下列:

Hash Join – 從較小的表構建一個哈希表,用連接列作爲哈希鍵。然後掃描較大的表,爲連接列計算哈希鍵並且探索哈希表尋找具有相同哈希鍵的行。哈希連接通常是Greenplum數據庫中最快的連接。解釋計劃中的Hash Cond標識要被連接的列。
Nested Loop – 在較大數據集的行上迭代,在每次迭代時於較小的數據集中掃描行。嵌套循環連接要求廣播其中的一個表,這樣一個表中的所有行才能與其他表中的所有行進行比較。它在較小的表或者通過使用索引約束的表上執行得不錯。它還被用於笛卡爾積和範圍連接。在使用Nested Loop連接大型表時會有性能影響。對於包含Nested Loop連接操作符的計劃節點,應該驗證SQL並且確保結果是想要的結果。設置服務器配置參數enable_nestloop爲OFF(默認)能夠讓優化器更偏愛Hash Join。
Merge Join – 排序兩個數據集並且將它們合併起來。歸併連接對預排序好的數據很快,但是在現實世界中很少見。爲了更偏愛Merge Join,可把系統配置參數enable_mergejoin設置爲ON。
一些查詢計劃節點指定移動操作。在處理查詢需要時,移動操作在Segment之間移動行。該節點標識執行移動操作使用的方法。Motion操作符包括下列:

Broadcast motion – 每一個Segment將自己的行發送給所有其他Segment,這樣每一個Segment實例都有表的一份完整的本地拷貝。Broadcast motion可能不如Redistribute motion那麼好,因此優化器通常只爲小型表選擇Broadcast motion。對大型表來說,Broadcast motion是不可接受的。在數據沒有按照連接鍵分佈的情況下,將把一個表中所需的行動態重分佈到另一個Segment。
Redistribute motion – 每一個Segment重新哈希數據並且把行發送到對應於哈希鍵的合適Segment上。
Gather motion – 來自所有Segment的結果數據被組裝成一個單一的流。對大部分查詢計劃來說這是最後的操作。
查詢計劃中出現的其他操作符包括:

Materialize – 規劃器將一個子查詢物化一次,這樣就不用爲頂層行重複該工作。
InitPlan – 一個預查詢,被用在動態分區消除中,當執行時還不知道規劃器需要用來標識要掃描分區的值時,會執行這個預查詢。
Sort – 爲另一個要求排序數據的操作(例如Aggregation或者Merge Join)準備排序數據。
Group By – 通過一個或者更多列分組行。
Group/Hash Aggregate – 使用哈希聚集行。
Append – 串接數據集,例如在整合從分區表中各分區掃描的行時會用到。
Filter – 使用來自於一個WHERE子句的條件選擇行。
Limit – 限制返回的行數。
優化Greenplum查詢
這個主題描述可以用來在某些情況下提高系統性能的Greenplum數據庫特性和編程實踐。

爲了分析查詢計劃,首先找出估計代價非常高的計劃節點。判斷估計的行數和代價是不是和該操作執行的行數相關。

如果使用分區,驗證是否實現了分區消除。要實現分區消除,查詢謂詞(WHERE子句)必須與分區條件相同。還有,WHERE子句不能包含顯式值且不能含有子查詢。

審查查詢計劃樹的執行順序。審查估計的行數。用戶想要執行順序構建在較小的表或者哈希連接結果上並且用較大的表來探查。最優情況下,最大的表被用於最後的連接或者探查以減少傳遞到樹最頂層計劃節點的行數。如果分析結果顯示構建或探查的執行順序不是最優的,應確保數據庫統計信息爲最新。運行ANALYZE將能更新數據庫統計信息,進而產生一個最優的查詢計劃。

查找計算性傾斜的跡象。當Hash Aggregate和Hash Join之類的操作符的執行導致Segment上的不平均執行時,查詢執行中會發生計算性傾斜。在一些Segment上會使用比其他更多的CPU和內存,導致非最優的執行。原因可能是在具有低基數或者非一致分佈的列上的連接、排序或者聚集。用戶可以在查詢的EXPLAIN ANALYZE語句中檢測計算性傾斜。每個節點包括任一Segment所處理的最大行數以及所有Segment處理的平均行數。如果最大行數遠大於平均數,那麼至少有一個Segment執行了比其他更多的工作,因此應該懷疑該操作符出現了計算性傾斜。

確定執行Sort或者Aggregate操作的計劃節點。Aggregate操作下隱藏的就是一個Sort。如果Sort或者Aggregate操作涉及到大量行,這就是改進查詢性能的機會。在需要排序大量行時,HashAggregate操作是比Sor和Aggregate操作更好的操作。通常優化器會因爲SQL結構(也就是由於編寫SQL的方式)而選擇Sort操作。在重寫查詢時,大部分的Sort操作可以用HashAggregate替換。要更偏愛HashAggregate操作而不是Sort和Aggregate,請確保服務器配置參數enable_groupagg被設置爲ON。

當解釋計劃顯示帶有大量行的廣播移動時,用戶應該嘗試消除廣播移動。一種方法是使用服務器配置參數gp_segments_for_planner來增加這種移動的代價估計,這樣優化器會偏向其他可替代的方案。gp_segments_for_planner變量告訴查詢規劃器在其計算中使用多少主Segment。默認值是零,這會告訴規劃器在估算中使用實際的主Segment數量。增加主Segment的數量會增加移動的代價,因此會更加偏向重新分佈移動。例如,設置gp_segments_for_planner = 100000會告訴規劃器有100,000個Segment。反過來,要影響規劃器廣播表而不是重新分佈它,可以把gp_segments_for_planner設置爲一個較低的值,例如2。

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