由於資料分布和查詢複雜度等因素,可能出現查詢效能不符合預期的情況,檢查查詢的執行計畫是重要的問題排查方式之一。
常見計劃問題
- Join Method以及Inner和Outer表
根據Join Method選擇Inner和Outer表, 一般情況下AnalyticDB MySQL版自動選擇Join的左右表,您也可以自行檢查左右表的選擇是否合理。
Hash Join中,右表建立Hash,左表去右表中尋找合格資料,一般右表要盡量小於左表,以減少建立Hash表的開銷以及Hash表的大小。您可以通過檢查Join表過濾後的大小來查看對應的左右表選擇是否合理。但由於還有多表Join的中間結果,以及Join Type等因素影響,Join的左右表的選擇也不能單純依賴表過濾後的大小來選擇。
- Join Order
Join Order的最佳化是最佳化器的核心挑戰之一,也是經典的NP-hard問題。AnalyticDB MySQL版最佳化器對於不同的負載提供兩種Join Reordering策略。Left Deep Tree(LDT)一般適用於較簡單查詢情境,Bushy Tree(BT)適用較複雜的負載查詢。Bushy Tree一般會將過濾效果更好的表放在前面,對於複雜查詢能夠產生更優的Join Order。
對於複雜查詢,人為確認最佳Join Order非常困難。Join表數量較大時,需要資深的專家進行調優。建議將過濾效果更好的表放在Join Sequence之前,可以更早更快的過濾掉不需要的資料。
- 分布式Aggregation
AnalyticDB MySQL版提供分布式彙總計算能力,可以根據計算資料量分步做彙總計算。一般情況下,AnalyticDB MySQL版的最佳化器可以選擇最佳彙總計算計劃,但在資料扭曲比較嚴重等情境下,最佳化器對於彙總資料分布估算的誤差會比較大,從而造成彙總計算效能問題。例如,一般AnalyticDB MySQL版會選擇兩階段彙總計算,在各個計算節點本地做一次部分彙總(Partial Aggregation),減少彙總計算資料量,然後再根據彙總列Reshuffle做一次Final Aggregation。一般情況下,部分彙總可以顯著減少彙總計算的資料量,但如果遇到資料扭曲嚴重,或者部分彙總列比較Unique從而不能減少彙總計算數量的情況下,部分彙總反而會帶來額外的效能開銷而非收益。
- 其它問題
本文只列舉了幾類常見的查詢計劃問題,例如全表掃描時出現無過濾條件的大表、可以下推的過濾條件沒有下沉到儲存等複雜計劃和效能問題等,需要AnalyticDB MySQL版專家服務小組來協助定位排查。
改進執行計畫
- 收集統計資訊
AnalyticDB MySQL版的查詢最佳化工具根據統計資訊估算不同計劃的開銷,並選擇最佳計劃。統計資訊會自動收集,一般不需要使用者關心,詳情請參見自動收集統計資訊。對於建立的表,系統可能還未及時收集統計資訊,您可以通過
select * from information_schema.column_statistics;查看查詢關聯的表是否有統計資訊(3.1.6及之後的版本才有此系統資料表)。如果查詢關聯的表沒有統計資訊,可以先手動執行收集命令收集一次,之後交給自動收集模組去收集即可。手動收集統計資訊的詳情,請參見手動收集統計資訊。 - 調整Join Order
通常AnalyticDB for MySQL可以選擇最佳的Join Order,由於資料分布特性以及查詢自身的複雜度等因素,在某些情境下可能存在無法選擇最優Join Order,查詢效能較低,您可以通過在Hint中引入
reorder_joins參數設定是否手動調整Join Order。/*+reorder_joins=false*/;,開啟手動調整Join Order開關,然後通過修改查詢中各個表出現的順序來控制Join Order。/*+reorder_joins=true*/;,關閉手動調整Join Order開關,系統會自動選擇Join Order,絕大多數情境下可以獲得最佳Join Order。
例如上述樣本中的nation、region、customer表,AnalyticDB MySQL版給出的Join Order是region > nation > customer。如果根據實際查詢效能得出更好的Join Order:customer > nation > region,可以如下所示在查詢前使用Hint改變查詢中表的順序。/*+ reorder_joins=false */ EXPLAIN SELECT count(*) FROM customer, nation, region WHERE c_nationkey = n_nationkey AND n_regionkey = r_regionkey AND r_name = 'ASIA';| Plan Summary | +---------------+ 1- Output[ Query plan ] 2 -> Aggregate (FINAL) 3 -> LocalExchange[SINGLE] 4 -> Exchange[GATHER] 5 -> Aggregate (PARTIAL) 6 -> InnerJoin[Hash Join] 7 - Project 8 -> InnerJoin[Hash Join] 9 - ScanProject {table: customer} 10 -> TableScan {table: customer} 11 -> LocalExchange[HASH] 12 -> Exchange[REPLICATE] 13 - ScanProject {table: nation} 14 -> TableScan {table: nation} 15 -> LocalExchange[HASH] 16 -> Exchange[REPLICATE] 17 - ScanProject {table: region} 18 -> TableScan {table: region}
查詢計劃調優是一個非常廣泛的領域,本文簡要討論AnalyticDB MySQL版中的查詢計劃調優基礎方法,後續將不斷更新更多的調優最佳實務。