SQL優(yōu)化之多表join

關(guān)于Join

如上圖所示兜喻,left join和inner join的取值范圍還是有很明顯的不同的赡麦,看網(wǎng)上不少文章優(yōu)化left join也不交代上下文環(huán)境朴皆,直接就是教唆把left join換成inner join,只能說是章口就萊泛粹,文體兩開花...

關(guān)于笛卡爾積

簡言之就是強(qiáng)拼,不帶條件的硬拼2(多)張表晶姊,結(jié)果就是直接做乘法

SELECT * FROM a CROSS JOIN b;

SELECT * FROM a INNER JOIN b;

SELECT * FROM a,b;

SELECT * FROM a NATURE JOIN b;

SELECT * FROM a NATURA join b;

如何判斷驅(qū)動表

如果沒有where條件

左連接帽借,如果沒有where條件,則左表為驅(qū)動表

右連接脆荷,如果沒有where條件梦皮,右表為驅(qū)動表

如果有where條件

(參照《數(shù)據(jù)庫索引設(shè)計(jì)與優(yōu)化》第8章內(nèi)容對外表的判定應(yīng)該是下面寫的這個(gè)樣子)

(參考讀書筆記:索引讀書筆記

但是實(shí)際操作中有本地謂詞的表并不一定百分百的是外表炭分,而是由優(yōu)化器來判斷的


#個(gè)人實(shí)際優(yōu)化過程中用的最多的還是下面這條

explain規(guī)則:explain語句結(jié)果中,第一行為驅(qū)動表(該定律適用于join剑肯;子查詢的話要分情況)


性能優(yōu)化相關(guān)

①選誰做驅(qū)動表

引用一個(gè)舉爛了的例子捧毛,在沒有過濾條件的情況下,外表有多少行就會被加載多少次让网;參考《索引設(shè)計(jì)與優(yōu)化》這本書的說法呀忧,每次加載相當(dāng)于一次隨機(jī)讀

假設(shè)A表10000行溃睹,B表100行而账;也就是說如果用A表做驅(qū)動表會伴隨著10000次隨機(jī)讀,而如果是B表作為驅(qū)動表因篇,會伴隨著100次隨機(jī)讀泞辐。

所以普遍的優(yōu)化方案是小表作為外表(驅(qū)動表),用小表去驅(qū)動大表竞滓。


②創(chuàng)建合理的索引

選擇小表驅(qū)動大表咐吼,然后在內(nèi)表(被驅(qū)動的大表)的連接謂詞上建立索引,使得對內(nèi)表的查詢走索引提高效率虽界。這種做法最高效的就是外表是一張小表汽烦,而內(nèi)表的連接謂詞剛好是內(nèi)表的主鍵涛菠。

在對這種沒有查詢過濾條件的語句執(zhí)行explain的時(shí)候會非常不爽莉御,因?yàn)轵?qū)動表通常是走的全表掃描;在我的測試中俗冻,如果外表上沒有查詢過濾條件(也就是本地謂詞)的話礁叔,無論查詢項(xiàng)是否是索引項(xiàng),都是走全表迄薄。(換句話說琅关,也就是在沒有過濾條件的情況下,外表其實(shí)有沒有索引對于當(dāng)前語句的優(yōu)化意義都不太明顯(因?yàn)闀呷砺铮┘ケ危绻麑iT因?yàn)槟硞€(gè)語句去對外表建一大堆索引的可以省省了)

#用下面的例子來解釋上面2句話

m表和t表都是25W行左右涣易,大小差距不大;根據(jù)開篇說的驅(qū)動表確立規(guī)則冶伞,無查詢過濾條件的左連接新症,左表為驅(qū)動表;藍(lán)框表明了這一點(diǎn)响禽。

綠框的t.charge_no是t表的連接謂詞徒爹,在這一列上建有一個(gè)選擇性不錯(cuò)的索引荚醒,因此在explain的第二行可以看到內(nèi)表的查詢走了索引,type為ref隆嗅,效率還算不錯(cuò)界阁。(如果這個(gè)連接謂詞是t表的主鍵,效率會更高)

紅框處可以看到胖喳,對m表取的查詢值泡躯,我們僅僅取了m.charge_no這一列,而且m.charge_no上是建有索引的禀晓,但explain的第一行粉框的ALL表明m表的查詢?nèi)匀蛔吡巳恚词故俏覀僲表的查詢列只取了建有索引的列)精续。


#如何讓外表走索引?

方法:對外表增加過濾條件(本地謂詞)粹懒,并且在本地謂詞上創(chuàng)建索引

查詢過濾條件中只有t表的本地謂詞重付,因此無論左連接還是右連接,t表都是驅(qū)動表

由于過濾條件t.partner_id和t.trade_date上建有索引凫乖,因此外表t不再走全表掃描

注意2處藍(lán)框是有關(guān)聯(lián)的确垫,右下角的那個(gè)大藍(lán)框里面是沒有temporary的,這與接下來討論的有關(guān)


③合理的排序

前面2張圖里面的語句是我在項(xiàng)目中遇到的一個(gè)慢查詢帽芽,本體并非前面2張圖貼出的那樣删掀,區(qū)別在于order by后面跟的字段不同,原語句order by后面跟著的是一個(gè)內(nèi)表字段

多表join執(zhí)行時(shí)导街,優(yōu)化器內(nèi)部會先找出外表披泪,之后會對外表進(jìn)行排序;如果order by后面跟的是外表字段搬瑰,則排序會在這時(shí)完成款票。但如果order by后面的字段是內(nèi)表字段,則在所有結(jié)果集選出之后泽论,再進(jìn)行一次排序艾少,這也就是執(zhí)行計(jì)劃里面Using temporary的由來了。

項(xiàng)目中的原語句一來沒有本地謂詞翼悴,二來還用內(nèi)表進(jìn)行排序缚够,導(dǎo)致最后的執(zhí)行時(shí)間達(dá)到8s之久;與研發(fā)溝通之后將語句改成用外表字段排序鹦赎,執(zhí)行時(shí)間所短到0.3s谍椅。


④強(qiáng)行指定驅(qū)動表

左右連接都可以指定驅(qū)動表,但(inner) join無法強(qiáng)行指定古话,通常來說都是通過系統(tǒng)自動去判定

強(qiáng)行指定方式:straight_join

這個(gè)參數(shù)會強(qiáng)行指定左表是外表

例子就截個(gè)別人的圖吧


多表join優(yōu)化案例

eg.

紅框處是可能需要加索引的各種連接謂詞和本地謂詞雏吭,藍(lán)框標(biāo)示了執(zhí)行順序掃描方式等幫助信息

#對執(zhí)行計(jì)劃進(jìn)行分析

在執(zhí)行計(jì)劃的第5行可以發(fā)現(xiàn)pcb表走了全表掃描,掃描行數(shù)達(dá)到95W行煞额;通過執(zhí)行計(jì)劃的第4行可以發(fā)現(xiàn)這里有一個(gè)派生表思恐,這個(gè)派生表是由pcb和ppv做inner join形成的沾谜,這里很明顯pcb成了這個(gè)連接查詢的外表,查詢ppv表胀莹,發(fā)現(xiàn)ppv表僅僅只有19行基跑。這是典型的大表驅(qū)動小表

查詢pcb表的索引,發(fā)現(xiàn)pcb表的連接謂詞和本地謂詞上面都沒有建索引描焰!而ppv.id是ppv表的主鍵(mysql優(yōu)化器大概就是因?yàn)檫@個(gè)原因讓ppv表做了內(nèi)表吧...)

把pcb表的連接謂詞和本地謂詞做了一個(gè)聯(lián)合索引之后媳否,掃描行數(shù)從95W縮減至5.4W,優(yōu)化器很識趣的將ppv選做外表了

消滅了95W行的掃描之后荆秦,盤面上最刺眼的就是第二行那個(gè)2871了篱竭,對pc表的索引進(jìn)行查詢發(fā)現(xiàn)pc.client_no列上也沒有索引,由于pc.client_no列是一個(gè)本地謂詞步绸,在添加索引之后掺逼,pc表直接跳到了explain的第一行。優(yōu)化后的執(zhí)行計(jì)劃如下圖

對比pp表和pc表瓤介,pp表有16行數(shù)據(jù)吕喘,pc表有3000行數(shù)據(jù),都不算太大刑桑,無論誰作為驅(qū)動表都不會有太大的性能提升了氯质,優(yōu)化也到此結(jié)束;執(zhí)行時(shí)間由1s縮減到0.29s


參考文章

1.MySQL的JOIN

2.《索引設(shè)計(jì)與優(yōu)化》

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末祠斧,一起剝皮案震驚了整個(gè)濱河市闻察,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌琢锋,老刑警劉巖辕漂,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吩蔑,居然都是意外死亡钮热,警方通過查閱死者的電腦和手機(jī)填抬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門烛芬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人飒责,你說我怎么就攤上這事赘娄。” “怎么了宏蛉?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵遣臼,是天一觀的道長。 經(jīng)常有香客問我拾并,道長揍堰,這世上最難降的妖魔是什么鹏浅? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮屏歹,結(jié)果婚禮上隐砸,老公的妹妹穿的比我還像新娘。我一直安慰自己蝙眶,他們只是感情好季希,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著幽纷,像睡著了一般式塌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上友浸,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天峰尝,我揣著相機(jī)與錄音,去河邊找鬼收恢。 笑死境析,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的派诬。 我是一名探鬼主播劳淆,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼默赂!你這毒婦竟也來了沛鸵?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤缆八,失蹤者是張志新(化名)和其女友劉穎曲掰,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體奈辰,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡栏妖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奖恰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吊趾。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖瑟啃,靈堂內(nèi)的尸體忽然破棺而出论泛,到底是詐尸還是另有隱情,我是刑警寧澤蛹屿,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布屁奏,位于F島的核電站,受9級特大地震影響错负,放射性物質(zhì)發(fā)生泄漏坟瓢。R本人自食惡果不足惜勇边,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望折联。 院中可真熱鬧粥诫,春花似錦、人聲如沸崭庸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽怕享。三九已至执赡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間函筋,已是汗流浹背沙合。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留跌帐,地道東北人首懈。 一個(gè)月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像谨敛,于是被迫代替她去往敵國和親究履。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

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