效能調優7 多表連線 join

2022-01-10 07:38:37 字數 4271 閱讀 6836

在產品環境中,往往存在著大量的表連線情景,不管是inner join、outer join、cross join和full join(邏輯連線符號),在內部都會轉化為物理連線(physical join),sql server共有三種物理連線:nested loop(巢狀迴圈),merge join(合併連線)和hash join(雜湊連線)。這三個物理連線的處理方式不同,分別應用在不同的場景中。通過query hint來指定物理連線: with( join)

在同一時刻,表連線只能是兩表(或者是資料集,也就是表的一部分)之間的連線,通常按照表處於join操作的位置來區分,把join操作符前面的表叫做左表,把join操作符後面的表叫做右表。如果有n個表連線,那麼必須進行n-1次關聯操作,上一次關聯操作的結果作為下一次關聯操作的乙個資料集。on子句用於設定連線條件,可以決定連線的順序。

巢狀迴圈是最基本的join演算法,分為兩個迴圈,內部迴圈和外部迴圈,內部迴圈巢狀在外部迴圈內部。任何乙個連線語句,都包含兩個表,內部迴圈對應內部表,外部迴圈對應外部表。在圖形執行計畫中,上面的輸入表是外部表,下面的輸入表是內部表。

在巢狀迴圈中,外部迴圈逐行處理外部表,內部迴圈針對每乙個外部行到內部表中進行查詢,以找出所有匹配外部行的資料行。外部迴圈每輸出一行,內部表中所有行都會和外部行進行匹配,假如外部表有n行,內部表有m行,對於外部表的每一行,內部表都會匹配m行,這種演算法的開銷是基於外部表的行數 乘以內部表的行數來確定,即以 n*m 來確定開銷。

如果內部迴圈在連線條件上存在索引,那麼把連線條件的每乙個值叫做關聯引數(correlated parameter),使用關聯引數可以應用index seek演算法去查詢匹配行。

巢狀迴圈適用於:大表和小表進行連線,並且大表在連線條件上存在索引。當把外部表是小表,內部表是大表,且內部表是在連線列上有索引時,優化器傾向於使用巢狀迴圈。優化器對巢狀迴圈的優化是:

1,如果內部表在連線列上存在索引,那麼優化器把外部表的輸入行作為關聯引數,基於關聯引數對內部表使用index seek查詢

2,對內部表使用lazy spool,spool是指快取中間結果集,以便重用。當內部表在連線條件上有很多重複值,但只有少數行可以和外部行匹配時,nested loop演算法的效率非常高。

不是所有的join都有相關引數,如果沒有合適的索引,或者on子句沒有指定合適的連線條件,就不會使用index seek演算法,也就不會有相關引數,通常情況下,inner join和left join 可以有相關引數,而right join,cross join和full join 沒有相關引數。

合併連線使用的是合併演算法,要求至少存在乙個相等的連線謂詞(on子句中至少存在乙個相等條件),並且兩個輸入在合併列上必須是有序的。通常情況下,查詢優化器會掃瞄表上的索引,以檢查是否有索引包含合併列;如果沒有適當的索引,那麼合併連線的後面使用sort操作符對合併列進行排序,索引和sort操作符都是為了滿足「合併演算法對兩個輸入必須是有序的」這一硬性要求。合併連線,也稱作排序-合併-連線(sort-merge-join)。

如果合併連線需要對資料集進行排序,那麼還需要為sort操作符向系統申請授予記憶體(granted memory),以儲存排序的中間結果集。如果查詢語句輸出的結果在連線鍵上是有序,order by join-keys,那麼連線查詢傾向於使用合併連線,如果排序是不必要的,那麼可以去掉order by子句。

由於兩個輸入都已經排序,merge join操作符從每一輸入各獲取一行進行比較,例如,對於inner join,如果兩行相等,則放回這個相等的結果;如果不相等,則廢棄值較小的行,並從該輸入中獲取下一行。這一過程重複進行,直到處理完所有的資料行。

如果兩個輸入是有序的資料,那麼merge join的執行速度很快,但是,當需要新增sort操作符對輸入資料進行排序時,選擇使用merge join操作符將十分費時。對於資料量大,並且可以從b-tree索引中獲得已排序的資料,那麼merge join是執行速度最快的連線演算法。 

雜湊連線(hash join)適用於無序的大表之間的連線,有兩個輸入:生成輸入(build input) 和 探測輸入(porbe input),查詢優化器使用兩個輸入中較小的作為生成輸入。雜湊連線掃瞄生成輸入,載入到記憶體中,生成雜湊表,這個過程叫做生成階段(build phrase)。當生成輸入的所有行都載入到hash 表之後,開始探測階段(probe phrase):對於探測輸入的每一行,計算其hash值,和雜湊表進行匹配,輸出匹配的資料行。在探測階段,每做一次雜湊連線操作,探測輸入的每一行只會掃瞄一次,再根據雜湊鍵值去掃瞄整個雜湊表。

hash連線的兩個階段是有先後順序的,生成階段在前,探測階段在後。hash連線在生成階段需要生成hash table,這需要向系統申請授予記憶體(granted memory),以儲存hash值,如果授予記憶體不足,那麼hash連線就不會開始。

1,雜湊連線的記憶體消耗和溢位

在hash連線開始執行前,sql server嘗試估計需要多少記憶體去建立hash表,優化器使用預估的行數和每行的平均大小去估算需要的記憶體大小。為了最小化記憶體的使用,優化器從兩個表中選擇乙個小表作為生成輸入(build input),sql server通過向系統申請授予記憶體來保證hash表可以有「足夠」的記憶體建立成功。

如果sql server授予雜湊連線的記憶體小於實際需要的記憶體,那麼hash連線在生成階段會耗盡授予的記憶體,並把部分hash表的資料溢位到硬碟上,也就是tempdb的workfile檔案中。在這樣的情景下,hash連線維護的hash 桶(hash bucket)實際上儲存在兩個地方:記憶體中的hash表和硬碟上的workfile。

hash連線會記錄hash桶儲存的位置,當從生成輸入中繼續讀取一行資料時,它檢查該行是對映到記憶體的hash桶中,還是對映到硬碟的hash桶中,如果對映到記憶體的hash桶中,那麼把該hash值寫入到記憶體中;如果對映到硬碟的hash桶中,那麼把該hash值寫入到硬碟上的workfile結構中。

在探測階段,對於探測表的每一行,優化器都會檢查該行是對映到記憶體中的hash 桶,還是對映到硬碟上的hash 桶。如果對映到記憶體中hash桶,優化器就探測hash表,產生連線的資料集儲存到記憶體中,並捨棄當前行;如果對映到硬碟的hash桶,它會被寫入到硬碟中,暫時不做join運算,當hash的探測階段完成之後,hash連線會把溢位到硬碟的資料讀取到記憶體,為每個hash 桶重建記憶體hash表,做join運算。也就是說,雜湊連線把硬碟上的結果集和記憶體中的結果集合並為最終的結果集。

2,hash連線的效能優化

hash連線使用授予記憶體來建立雜湊表,如果授予記憶體不足,那麼部分雜湊桶就會被溢位到硬碟,硬碟的讀取和寫入都會影響雜湊連線的效能。因此,應該為hash連線分配足夠的授予記憶體。優化器使用統計資訊來預估授予記憶體的大小,如果統計資訊過時,導致預估的授予記憶體過小,這會嚴重降低hash連線的效能。

還有一種可能性是,參與hash連線的兩個表都很大,以至於不能分配足夠的記憶體來構建雜湊表,這也會導致雜湊桶被溢位到workfile,導致雜湊連線的效能低下。對於大表之間的對映,盡量使連線列有序,進而使用合併演算法來做連線。

3,雜湊連線的型別

本文只簡單介紹記憶體雜湊連線和grace 雜湊連線,對於遞迴雜湊連線(recursive hash join)和 hash bailout 是這兩個連線型別的優化,不再贅述。

(1),記憶體雜湊連線(in-memory hash join)

雜湊連線計算整個生成輸入,然後在記憶體中建立乙個雜湊表(hash table)。每乙個行都根據雜湊值(hash value)計算hash鍵,插入到相應的雜湊桶(hash bucket)中。如果整個生成輸入小於可能的記憶體,那麼所有的資料行都會被儲存到記憶體中雜湊表中。

(2),grace 雜湊連線(gracehash join

如果生成輸入太大,不能放到記憶體中,那麼hash join將會被處理成多個步驟,這就是grace 雜湊連線。每乙個步驟都有乙個生成階段和探測階段。首先,grace 雜湊連線使用乙個雜湊函式,把整個生成輸入和探測輸入按照hash鍵進行分割槽,把分割槽輸入到不同的檔案中,分割槽的規則是:

hash_func(join-field)

由於使用相同的hash演算法,在連線列上進行分割槽,這就保證了匹配的任意兩行資料都位於相同的檔案對中,我推測:檔案是在tempdb中建立的workfile,也就是說,需要呼叫io子系統,把資料寫入到硬碟中。grace hash join的主要的貢獻就在於,它使得每條資料只需要join一次。

grace 雜湊連線首先把兩個大的輸入,分割成多個小的輸入,然後再對每個檔案對進行雜湊連線操作,最後把每個分割槽join的結果合併作為連線操作最終輸出的結果。

advanced query tuning concepts

你真的了解join嗎?

Tomcat連線效能調優

tomcat是一款非常流行的apache的開源web伺服器。今天我們主要來 tomcat下面的server.xml中的聯結器配置對交易系統的效能影響。一種交易需要通過客戶端c來遠端hessian來同步呼叫服務端s的服務a來完成整筆交易,客戶端c設定的交易超時時間為60秒 比較簡單但不精準的做法是將客...

多表聯查(多表連線)(join)

多表聯查 多表連線 join 1 分類 內連線 自然連線 外鏈結 左外連線 右外連線 全外連線 mysql不支援 2 內連線 inner join 等值連線,制定對應的等值條件 select from emp,dept 得到的資料是不對的 得到的資料叫做笛卡爾積 結果是兩個表資料的乘積 使用內連線去...

調優 Nginx效能調優

一.nginx優化配置 1.主配置檔案優化 注 部分配置詳解 worker processes 8 nginx程序數,建議按照cpu數目來指定,一般為它的倍數。worker cpu affinity 00000001 00000010 00000100 00001000 00010000 00100...