Hash Join

1、Hash join 的兩個(gè)階段

第一階段是build揽碘,數(shù)據(jù)庫(kù)會(huì)讀取一個(gè)表的所有記錄生成一個(gè)保存在內(nèi)存中的hash表(對(duì)其中每個(gè)元組上的連接屬性(join attribute)采用哈希函數(shù)得到哈希值,從而建立一個(gè)哈希表)。這個(gè)階段往往會(huì)選擇較小的表生成hash表乌逐,因?yàn)閔ash表太大的話會(huì)占大量?jī)?nèi)存,而且也會(huì)消耗較多的cpu資源支子。build階段選擇的表也稱為left input或者build input。另外达舒,hash表的key就是兩個(gè)表join的equijoin字段值朋。

第二階段是probe,數(shù)據(jù)庫(kù)會(huì)逐一迭代另一個(gè)表的所有記錄來查詢hash表(即對(duì)另一個(gè)表巩搏,掃描它的每一行并計(jì)算連接屬性的哈希值昨登,與bulid phase建立的哈希表對(duì)比,若有落在同一個(gè)bucket的贯底,如果滿足連接謂詞(predicate)則連接成新的表)篙骡,從而生成join結(jié)果。probe階段選擇的表也稱為right input或者probe input。

NOTE:在build階段糯俗,hash join不會(huì)輸出任何結(jié)果;從probe階段開始睦擂,hash join才會(huì)輸出結(jié)果得湘。

2、Hash join 的內(nèi)存分配
如前文所說顿仇,build階段的hash表非常消耗內(nèi)存淘正。所以數(shù)據(jù)庫(kù)會(huì)從做join操作的兩個(gè)表中選擇較小的那個(gè)表來生成hash表,并且根據(jù)這個(gè)表的大小來預(yù)估并分配所需的內(nèi)存臼闻。但是鸿吆,如果內(nèi)存不夠會(huì)怎樣?這種情況下述呐,hash表會(huì)有一小部分保存在磁盤上惩淳,其他部分仍然保存在內(nèi)存中。當(dāng)我們從build input中讀取一條新的記錄的時(shí)候乓搬,如果hash表在內(nèi)存中思犁,那么我們就把記錄寫進(jìn)內(nèi)存;如果hash表在磁盤上进肯,那么我們就把記錄寫進(jìn)磁盤激蹲。類似地,probe階段如果內(nèi)存不夠江掩,也會(huì)把部分記錄寫進(jìn)磁盤学辱。

2、Hash join 的 Join Tree 類型
hash join tree的形狀會(huì)影響內(nèi)存的使用环形。如下圖所示策泣,hashjoin tree分為L(zhǎng)eft deep, right deep和 bushy hash斟赚。我們應(yīng)該根據(jù)表的size和join的結(jié)果來決定使用哪種tree着降,不過大多數(shù)情況下,我們可以直接使用sqlserver的優(yōu)化結(jié)果拗军。下文舉例一一介紹三種tree任洞。

hash join tree type

1)Left deep hash join
對(duì)于left deep,前一個(gè)join的probe output會(huì)成為下一個(gè)join的build input发侵,這樣同一時(shí)間只有相鄰的兩個(gè)pair會(huì)占用內(nèi)存交掏。所以對(duì)于上圖的left deep,峰值內(nèi)存是max(HJ1 + HJ2, HJ2 + HJ3)刃鳄。

select *
from (T1 join T2 on T1.a = T2.a)
join T3 on T1.b = T3.a

數(shù)據(jù)庫(kù)選擇了left deep tree: 我們先join T1 和 T2盅弛,并且因?yàn)門1比較小,所以選擇T1生成hash表。又因?yàn)楸敬蝚oin只生成了34條記錄遠(yuǎn)遠(yuǎn)小于T3挪鹏,所以基于本次join的輸出生成了下一次join的hash表见秽。我覺得,當(dāng)中間join的結(jié)果集較小的時(shí)候我們可以考慮用left deep讨盒。



2)right deep hash join
而對(duì)于right deep解取,前一個(gè)join的probe output會(huì)成為下一個(gè)join的probe input,這樣會(huì)導(dǎo)致所有的pair同時(shí)占用內(nèi)存計(jì)算hash表返顺,所以對(duì)于上圖的right deep禀苦,峰值內(nèi)存是max(HJ1 + HJ2 + HJ3)。

select *
from (T1 join T2 on T1.a = T2.a)
join T3 on T1.b = T3.a
where T1.a < 100

因?yàn)橛衱here T1.a < 100遂鹊,并且T1.a = T2.a振乏,所以有where T2.a < 100。因?yàn)門1和T2在where過濾之后都很小秉扑,所以sqlserver選擇了right deep tree慧邮,這樣兩個(gè)join操作可以基于這兩個(gè)表建立hash表,并且對(duì)較大的T3表做probe邻储。這樣要比基于join的中間結(jié)果生成hash表高效赋咽。我覺得,當(dāng)有一個(gè)大表多個(gè)小表的時(shí)候吨娜,可以考慮用right deep脓匿。


3)bushy hash join
對(duì)于bushy join,實(shí)際上是一顆平衡二叉樹宦赠,它使用的內(nèi)存會(huì)隨著樹的高度逐級(jí)減少陪毡。峰值內(nèi)存顯然是最底一層join的pair個(gè)數(shù),在上圖中應(yīng)該是max(HJ1 + HJ2)勾扭。

select * 
from (T1 join T3 on T1.a = T3.a) 
join
(T2 join T4 on T2.a = T4.a)
on T1.a = T2.a

使用option(force order)強(qiáng)制生成bushy形狀的tree毡琉。我們可以看到T1和T3,T2和T4分別做join妙色,然后對(duì)兩個(gè)join的結(jié)果再做join桅滋。可能是出于節(jié)省內(nèi)存的目的考慮身辨,sqlserver的優(yōu)化很少會(huì)生成bushy tree丐谋。我個(gè)人也覺得,bushy tree沒什么必要煌珊,因?yàn)閎ushy實(shí)際上可以用left deep或者right deep替代号俐。


參考:
https://www.freesion.com/article/426544799/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市定庵,隨后出現(xiàn)的幾起案子吏饿,更是在濱河造成了極大的恐慌踪危,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件猪落,死亡現(xiàn)場(chǎng)離奇詭異贞远,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)许布,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門兴革,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蜜唾,你說我怎么就攤上這事∈” “怎么了袁余?”我有些...
    開封第一講書人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)咱揍。 經(jīng)常有香客問我颖榜,道長(zhǎng),這世上最難降的妖魔是什么煤裙? 我笑而不...
    開封第一講書人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任掩完,我火速辦了婚禮,結(jié)果婚禮上硼砰,老公的妹妹穿的比我還像新娘且蓬。我一直安慰自己,他們只是感情好题翰,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開白布恶阴。 她就那樣靜靜地躺著,像睡著了一般豹障。 火紅的嫁衣襯著肌膚如雪冯事。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評(píng)論 1 290
  • 那天血公,我揣著相機(jī)與錄音昵仅,去河邊找鬼。 笑死累魔,一個(gè)胖子當(dāng)著我的面吹牛摔笤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播薛夜,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼籍茧,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了梯澜?” 一聲冷哼從身側(cè)響起寞冯,我...
    開封第一講書人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤渴析,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后吮龄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體俭茧,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年漓帚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了母债。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尝抖,死狀恐怖毡们,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情昧辽,我是刑警寧澤衙熔,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布,位于F島的核電站搅荞,受9級(jí)特大地震影響红氯,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜咕痛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一痢甘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茉贡,春花似錦塞栅、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至悔据,卻和暖如春庄敛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背科汗。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工藻烤, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人头滔。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓怖亭,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親坤检。 傳聞我的和親對(duì)象是個(gè)殘疾皇子兴猩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348