天天看點

一起來讀Greenplum/Deepgreen執行計劃

日常sql優化過程中,最好用的手段就是通過執行計劃。在greenplum和deepgreen中,運作 explain 後産生的執行計劃呈樹狀,這棵樹的每一個分叉,都代表了一個單獨的資料庫操作,例如:表掃描、表連接配接、聚合、排序。

由于傳回資料行數是從下向上傳遞的,是以我們在分析執行計劃時,也應該自下而上。通常來說,最底下的是表掃描操作(索引、位圖索引掃描)。如果查詢中涉及到連接配接、聚合、排序操作,那麼表掃描動作的上層就會有對應的這些操作。通常最頂上的部分是節點間資料移動(重分布、廣播、聚集操作),在查詢過程中,這些操作會涉及到在節點間移動資料。

explain 執行計劃中,每一個單獨的步驟都會呈現在單獨一行裡,帶有對應的動作類型及查詢資料所耗費的時間(查詢首行所用時間..查詢全部所用時間):

cost以磁盤頁讀取為測量機關,1.0等同于一個順序的磁盤頁讀取。第一個預估時間是起始消耗,即查詢首行所消耗的時間,第二個預估值是總消耗,即查詢全部行所用的時間。

rows指的是執行計劃某部分傳回的總行數。這個數量通常少于實際的傳回行數,反應的隻是一個預估的數量。最頂層的傳回的預估數量最接近實際查詢、修改或删除影響的行數。

操作傳回的所有資料所占用的位元組數。

很重要的一點是,上層節點所花費的時間包括是以子節點占用時間,計劃最頂層包含總執行花費的預估,這也是我們追求優化的部分。另外執行計劃的消耗隻與執行計劃本身關心的步驟有關,與查詢結果傳輸到用戶端的消耗時間等因素無關。

當我們分析查詢計劃時,是否有一個異常操作消耗了大部分的查詢時間?比如,在執行索引掃描時,時間比預期的要長很多,這時候我們基本可以判斷此索引可能已經超期了,需要重建。

我們通過運作 explain analyze ,檢視執行計劃預估的傳回行數與實際傳回的行數是否接近,如果出入很大,說明統計資訊是有問題的,我們需要對相關表/列收集更多的統計資訊。

在執行計劃中,選擇性限定條件應該更早的應用,目的是讓更少的資料傳回到上層操作中。如果查詢在選擇性限定條件應用後表現并不好,傳回的消耗依然很大,我們可以收集相關列的統計資訊再看看是否會提高性能;另外,還可以通過調整sql語句中不合理的 where 條件來提高性能。

當我們的查詢裡面有很多連接配接操作(join)時,要確定執行計劃選擇了一個最優連接配接順序。擁有大量傳回資料的連接配接應該盡早完成,以保證我們為上層操作傳回更少的行。如果執行計劃沒有選擇最佳的連接配接順序,我們可以設定參數 join_collapse_limit=1 ,然後在sql語句中使用明确的join文法強迫執行計劃按照特定的執行順序執行。另外,我們可以收集相關列的統計資訊再看看是否會提高性能。

如果我們使用查詢中涉及到了分區表資料查詢,那麼查詢計劃是否直接定位到掃描滿足條件的分區,而不是掃描整張表。

hash操作比其他類型的聚合或者連接配接操作要快很多,行資料的比較和分類操作是在記憶體中進行,而不是通過讀寫磁盤完成。為了能夠使用hash操作,我們必須保證有足夠的 work memory 可以容納查詢計劃傳回的行資料,是以我們可以通過嘗試增加work memory來提高查詢性能。通過運作explain analyze指令,這樣可以看出哪些計劃會有資料使用到磁盤,需要多少額外的work memory等,為work memory的調整提供參考。例如:

ends~