一起來讀Greenplum/Deepgreen執行計劃
日常SQL優化過程中,最好用的手段就是通過執行計劃。在Greenplum和Deepgreen中,運行 EXPLAIN 後產生的執行計劃呈樹狀,這棵樹的每一個分叉,都代表了一個單獨的數據庫操作,例如:表掃描、表連接、聚合、排序。
由於返回數據行數是從下向上傳遞的,所以我們在分析執行計劃時,也應該自下而上。通常來說,最底下的是表掃描操作(索引、位圖索引掃描)。如果查詢中涉及到連接、聚合、排序操作,那麼表掃描動作的上層就會有對應的這些操作。通常最頂上的部分是節點間數據移動(重分布、廣播、聚集操作),在查詢過程中,這些操作會涉及到在節點間移動數據。
EXPLAIN 執行計劃中,每一個單獨的步驟都會呈現在單獨一行裏,帶有對應的動作類型及查詢數據所耗費的時間(查詢首行所用時間..查詢全部所用時間):
1.cost
Cost以磁盤頁讀取為測量單位,1.0等同於一個順序的磁盤頁讀取。第一個預估時間是起始消耗,即查詢首行所消耗的時間,第二個預估值是總消耗,即查詢全部行所用的時間。
2.rows
rows指的是執行計劃某部分返回的總行數。這個數量通常少於實際的返回行數,反應的隻是一個預估的數量。最頂層的返回的預估數量最接近實際查詢、修改或刪除影響的行數。
3.width
操作返回的所有數據所占用的字節數。
很重要的一點是,上層節點所花費的時間包括所以子節點占用時間,計劃最頂層包含總執行花費的預估,這也是我們追求優化的部分。另外執行計劃的消耗隻與執行計劃本身關心的步驟有關,與查詢結果傳輸到客戶端的消耗時間等因素無關。
如果某個查詢的性能特別低,那麼我們可以通過查看執行計劃來定位問題原因。下麵是一些小技巧:
1.查詢計劃中是否有操作耗時特別的長?
當我們分析查詢計劃時,是否有一個異常操作消耗了大部分的查詢時間?比如,在執行索引掃描時,時間比預期的要長很多,這時候我們基本可以判斷此索引可能已經超期了,需要重建。
2.查詢計劃預估的時間和真實的時間接近嗎?
我們通過運行 EXPLAIN ANALYZE ,查看執行計劃預估的返回行數與實際返回的行數是否接近,如果出入很大,說明統計信息是有問題的,我們需要對相關表/列收集更多的統計信息。
3.選擇語句中的限定條件是否生效更早?
在執行計劃中,選擇性限定條件應該更早的應用,目的是讓更少的數據返回到上層操作中。如果查詢在選擇性限定條件應用後表現並不好,返回的消耗依然很大,我們可以收集相關列的統計信息再看看是否會提高性能;另外,還可以通過調整SQL語句中不合理的 WHERE 條件來提高性能。
4.查詢計劃是否選擇了最佳的JOIN順序?
當我們的查詢裏麵有很多連接操作(JOIN)時,要確保執行計劃選擇了一個最優連接順序。擁有大量返回數據的連接應該盡早完成,以保證我們為上層操作返回更少的行。如果執行計劃沒有選擇最佳的連接順序,我們可以設置參數 join_collapse_limit=1 ,然後在SQL語句中使用明確的JOIN語法強迫執行計劃按照特定的執行順序執行。另外,我們可以收集相關列的統計信息再看看是否會提高性能。
5.查詢計劃是否有選擇性的掃描分區表?
如果我們使用查詢中涉及到了分區表數據查詢,那麼查詢計劃是否直接定位到掃描滿足條件的分區,而不是掃描整張表。
6.查詢計劃是否適當的選擇Hash Aggregate和Hash Join操作?
Hash操作比其他類型的聚合或者連接操作要快很多,行數據的比較和分類操作是在內存中進行,而不是通過讀寫磁盤完成。為了能夠使用Hash操作,我們必須保證有足夠的 work memory 可以容納查詢計劃返回的行數據,所以我們可以通過嚐試增加work memory來提高查詢性能。通過運行EXPLAIN ANALYZE命令,這樣可以看出哪些計劃會有數據使用到磁盤,需要多少額外的work memory等,為work memory的調整提供參考。例如:
Work_mem used: 23430K bytes avg, 23430K bytes max (seg0).
Work_mem wanted: 33649K bytes avg, 33649K bytes max (seg0) to lessen workfile I/O affecting 2 workers.
Ends~
最後更新:2017-08-13 22:34:05