mysql left join 優(yōu)化

mysql 如何優(yōu)化left join

? 今天遇到一個left join優(yōu)化的問題亏栈,搞了一下午顾翼,中間查了不少資料挡毅,對MySQL的查詢計劃還有查詢優(yōu)化有了更進一步的了解,做一個簡單的記錄:

select c.* from hotel_info_original c

left join hotel_info_collection h

on c.hotel_type=h.hotel_type and c.hotel_id =h.hotel_id

where h.hotel_id is null

? 這個sql是用來查詢出c表中有h表中無的記錄暴构,所以想到了用left join的特性(返回左邊全部記錄,右表不滿足匹配條件的記錄對應(yīng)行返回null)來滿足需求段磨,不料這個查詢非常慢取逾。先來看查詢計劃:

? rows代表這個步驟相對上一步結(jié)果的每一行需要掃描的行數(shù),可以看到這個sql需要掃描的行數(shù)為35773*8134苹支,非常大的一個數(shù)字砾隅。本來c和h表的記錄條數(shù)分別為40000+和10000+,這幾乎是兩個表做笛卡爾積的開銷了(select * from c,h)债蜜。

于是我上網(wǎng)查了下MySQL實現(xiàn)join的原理晴埂,原來MySQL內(nèi)部采用了一種叫做 nested loop join的算法究反。Nested Loop Join 實際上就是通過驅(qū)動表的結(jié)果集作為循環(huán)基礎(chǔ)數(shù)據(jù),然后一條一條的通過該結(jié)果集中的數(shù)據(jù)作為過濾條件到下一個表中查詢數(shù)據(jù)儒洛,然后合并結(jié)果精耐。如果還有第三個參與 Join,則再通過前兩個表的 Join 結(jié)果集作為循環(huán)基礎(chǔ)數(shù)據(jù)琅锻,再一次通過循環(huán)查詢條件到第三個表中查詢數(shù)據(jù)卦停,如此往復(fù),基本上MySQL采用的是最容易理解的算法來實現(xiàn)join恼蓬。所以驅(qū)動表的選擇非常重要惊完,驅(qū)動表的數(shù)據(jù)小可以顯著降低掃描的行數(shù)。

那么為什么一般情況下join的效率要高于left join很多处硬?很多人說不明白原因小槐,只人云亦云,我今天下午感悟出來了一點荷辕。一般情況下參與聯(lián)合查詢的兩張表都會一大一小凿跳,如果是join,在沒有其他過濾條件的情況下MySQL會選擇小表作為驅(qū)動表桐腌,但是left join一般用作大表去join小表拄显,而left join本身的特性決定了MySQL會用大表去做驅(qū)動表,這樣下來效率就差了不少案站,如果我把上面那個sql改成

select c.* from hotel_info_original c

join hotel_info_collection h

on c.hotel_type=h.hotel_type and c.hotel_id =h.hotel_id

查詢計劃如下:

? ? 很明顯躬审,MySQL選擇了小表作為驅(qū)動表,再配合(hotel_id,hotel_type)上的索引瞬間降低了好多個數(shù)量級蟆盐。承边。。石挂。博助。

另外,我今天還明白了一個關(guān)于left join 的通用法則痹愚,即:如果where條件中含有右表的非空條件(除開is null)富岳,則left join語句等同于join語句,可直接改寫成join語句拯腮。

后記:

隨著查看MySQL reference manual對這個問題進行了更進一步的了解窖式。MySQL在執(zhí)行join時會把join分為system/const/eq_ref/ref/range/index/ALl等好幾類,連接的效率從前往后

依次遞減动壤,對于我的第一個sql萝喘,連接類型是index,所以幾乎是全表掃描的效果。但是我很奇怪我在(hotel_id,hotel_type)兩列上聲明了unique key阁簸,根據(jù)官方文檔連接類型應(yīng)該是eq_ref才對爬早,

? ? 這個問題一直困擾了我兩天,在google和stackoverflow上都沒有找到能夠解釋這個問題的文章启妹,莫非我這個問題無解了筛严?抱著解決這個問題的決心今天又翻看了一遍MySQL官方文檔

關(guān)于優(yōu)化查詢的部分,看到了這樣一句:這里的一個問題是MySQL能更高效地在聲明具有相同類型和尺寸的列上使用索引。我感覺我找到了問題所在,于是我將original和 collection表的(hotel_type,hotel_id)的encoding和collation(決定字符比較的規(guī)則)全部改成統(tǒng)一的utf8_general_ci乍恐,然后再次運行第一條sql的查詢計劃茴她,得到如下結(jié)果:

? ? 連接類型已經(jīng)由index優(yōu)化到了ref,如果將hotel_type申明為not null可以優(yōu)化到eq_ref,不過這里影響不大了,優(yōu)化后這條sql能在0.01ms內(nèi)運行完。

? ? 那么如何優(yōu)化left join:

1网杆、條件中盡量能夠過濾一些行將驅(qū)動表變得小一點,用小表去驅(qū)動大表

2伊滋、右表的條件列一定要加上索引(主鍵碳却、唯一索引、前綴索引等)笑旺,最好能夠使type達到range及以上(ref,eq_ref,const,system)

3昼浦、無視以上兩點,一般不要用left join~~筒主!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末关噪,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子乌妙,更是在濱河造成了極大的恐慌使兔,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件藤韵,死亡現(xiàn)場離奇詭異虐沥,居然都是意外死亡,警方通過查閱死者的電腦和手機泽艘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進店門欲险,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人匹涮,你說我怎么就攤上這事盯荤。” “怎么了焕盟?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我脚翘,道長灼卢,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任来农,我火速辦了婚禮鞋真,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘沃于。我一直安慰自己涩咖,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布繁莹。 她就那樣靜靜地躺著檩互,像睡著了一般。 火紅的嫁衣襯著肌膚如雪咨演。 梳的紋絲不亂的頭發(fā)上闸昨,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天,我揣著相機與錄音薄风,去河邊找鬼饵较。 笑死,一個胖子當(dāng)著我的面吹牛遭赂,可吹牛的內(nèi)容都是我干的循诉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼撇他,長吁一口氣:“原來是場噩夢啊……” “哼茄猫!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起逆粹,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤募疮,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后僻弹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體阿浓,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年蹋绽,在試婚紗的時候發(fā)現(xiàn)自己被綠了芭毙。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡卸耘,死狀恐怖退敦,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情蚣抗,我是刑警寧澤侈百,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響钝域,放射性物質(zhì)發(fā)生泄漏讽坏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一例证、第九天 我趴在偏房一處隱蔽的房頂上張望路呜。 院中可真熱鬧,春花似錦织咧、人聲如沸胀葱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抵屿。三九已至,卻和暖如春手趣,著一層夾襖步出監(jiān)牢的瞬間晌该,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工绿渣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留朝群,地道東北人。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓中符,卻偏偏與公主長得像姜胖,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子淀散,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

推薦閱讀更多精彩內(nèi)容