本文分享自華為雲社區《GaussDB(DWS)等待視圖之Hashjoin-nestloop》,作者:Arrow0lf。 1. 業務場景 眾所周知,GaussDB(DWS)中有3種常見的join方式:HashJon/MergeJoin/NestLoop 但在有一些場景中,等待視圖中等待狀態會顯示為:H ...
本文分享自華為雲社區《GaussDB(DWS)等待視圖之Hashjoin-nestloop》,作者:Arrow0lf。
1. 業務場景
眾所周知,GaussDB(DWS)中有3種常見的join方式:HashJon/MergeJoin/NestLoop
但在有一些場景中,等待視圖中等待狀態會顯示為:HashJoin-nestloop,如下圖所示。這種表示什麼含義?
2. 基本原理
為了明白該狀態的原因,首先思考如下場景:當業務側兩張大表join時,如果由於未做analyze或統計信息不准,導致build hash的一側選擇了大表,且該表在join列上重覆值很多,會導致hashjoin時記憶體膨脹,當記憶體不足時,hashjon運算元會下盤,但是由於join列上存在大量重覆值,下盤文件無法有效分裂,此時,如果將整個文件都讀取到記憶體中,會導致記憶體占用很高,出現記憶體過載,導致其他業務記憶體不足報錯。
為瞭解決該場景,在向量化hashjoin時,當使用內表創建的hash表過大導致記憶體不足時,不再強制進行hashjoin,會通過內外表交換或執行nestloop使查詢平穩進行,防止出現記憶體報錯,此時,等待視圖狀態為“HashJoin-nestloop”
上述特性通過hashjoin_spill_strategy參數控制,預設為0,取值範圍為0-6的整數,詳情可以參考產品文檔(8.1.2及以上版本),簡單來講:
取值為0或5,hashjoin時會先嘗試內外表交換,如果仍然記憶體占用高,會選擇nestloop;
取值為1或6,hashjoin時會先嘗試內外標交換,如果仍然記憶體占用高,會強行執行hashjoin;
取值為2,hashjoin行為和原本的行為保持一致,即使記憶體不夠,也會強制執行hashjoin
3. 業務影響
當等待視圖出現Hashjoin-nestloop時,可能會導致原來記憶體占用高,單能執行成功的語句,在被轉換成nestloop後,可能會短時間執行不出來。尤其是當數據量變化較大,統計信息差異較大時,容易出現執行計劃非最優場景下的性能劣化。
4. 解決方法
如果出現上述HashJoin-nestloop時間長,導致業務超時的情況。可以將參數hashjoin_spill_strategy設置為2進行規避。不再進行內外表交換或執行nestloop,使業務行為與之前的行為保持一致。
在記憶體充裕的場景下,可以全局設置為2。