今天就跟大家聊聊有關MySQL中Join的執(zhí)行過程有哪些,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
創(chuàng)新互聯(lián)是一家從事企業(yè)網(wǎng)站建設、成都做網(wǎng)站、成都網(wǎng)站設計、行業(yè)門戶網(wǎng)站建設、網(wǎng)頁設計制作的專業(yè)網(wǎng)站制作公司,擁有經(jīng)驗豐富的網(wǎng)站建設工程師和網(wǎng)頁設計人員,具備各種規(guī)模與類型網(wǎng)站建設的實力,在網(wǎng)站建設領域樹立了自己獨特的設計風格。自公司成立以來曾獨立設計制作的站點近1000家。MySQL的Join是如何執(zhí)行的
join可以說一種集合的運算,比如left join,right join,inner join,full join,outer join,cross join等,這些集合間的計算關系對應在高中數(shù)學集合里面的交集,并集,補集,全集等。但在實際的代碼中,join運算基本上是通過多層循環(huán)來實現(xiàn)的。
舉一個例子,假設有t1,t2兩張表,表結構分別如下:
createtablet1(
idintnotnullAUTO_INCREMENT,
usernamevarchar(20)notnulldefault'',
ageintnotnulldefault0,
PRIMARYkey(`id`)
)ENGINE=INNODBDEFAULTCHARSET=UTF8MB4;
createtablet2(
idintnotnullauto_increment,
usernamevarchar(20)notnulldefault'',
scoreintnotnulldefalut0,
primarykey(`id`)
))ENGINE=INNODBDEFAULTCHARSET=UTF8MB4;
假設t1有100條數(shù)據(jù),t2表有200條數(shù)
查詢sql為:
selectt1.*,t2.*fromt1leftjoint2on(t1.username=t2.username)
那么這條SQL的執(zhí)行步驟如下:
從表t1中取一行數(shù)據(jù)r1
從r1中,取出字段username到表t2中查詢
取出表t2中滿足條件的行,跟r1組成一行,作為結果集的一部份
重復執(zhí)行步驟1,2,3,直到表t1的所以數(shù)據(jù)循環(huán)完畢
基本上先遍歷t,1,然后根據(jù)t1中的每行數(shù)據(jù)中的username,去表t2中查找滿足條件的記錄?;揪褪?層循環(huán)。
如何優(yōu)化join查詢
從上面可以看出,join本質(zhì)是循環(huán),這里的開銷如下:
遍歷t1數(shù)據(jù),讀取數(shù)據(jù)為t1表的行數(shù),假設行數(shù)為n,則復雜度也為n
根據(jù)t1的匹配字段username去t2中一行一行的查詢數(shù)據(jù)
這個過程,因為MySQL的數(shù)據(jù)存儲結構為二叉樹,時間復雜度為log2(m) m為t2表的總行數(shù)
那么總復雜度近似為 n+n(2log2(m))
從上面的步驟可以看出,優(yōu)化方向:
降低t1查詢時的開銷,主要是磁盤io開銷,避免全表掃描,用索引
降低t2查詢時的開銷,也用索引
將數(shù)據(jù)量多的表做被驅(qū)動表,小表作驅(qū)動表,m取了對數(shù),大表數(shù)據(jù)量大對復雜度的影響沒有線性增長
緩存t1表,不用每次去磁盤load,比如一次緩存100條,那么能顯著降低磁盤讀數(shù)據(jù)次數(shù),t2每次與緩存中的t1數(shù)據(jù)進行比較
隨機磁盤讀比較耗費磁盤性能,轉(zhuǎn)為順序讀,因為二叉樹的存儲結構,每次非主鍵查找,有一個回表的動作,即根據(jù)主鍵再次查詢需要的數(shù)據(jù)
優(yōu)化的基本方法:
減少循環(huán)次數(shù),減少磁盤IO次數(shù),變隨機IO為順序IO
其實MySQL針對上面的優(yōu)化方法有對應的算法:
Simple Nested Loop Join 最普通的循環(huán),這個要避免
Block Nested Loop Join 主要是針對t2表上沒有索引,在步驟2將t2中的每一行數(shù)據(jù)跟join buffer數(shù)據(jù)做對比,這樣將磁盤操作轉(zhuǎn)為內(nèi)存操作進行比較,但是如果被驅(qū)動表的數(shù)據(jù)比較大的話,也影響性能,主要是cache pool被占滿,導致MySQL性能下降
Index Nested Join 就是都通過主鍵進行查找關聯(lián),這種性能比較好
Batched Key Access Join 這個是 Index Nested Join上做的優(yōu)化,因為回表的存在,隨機操作io也很耗費性能,這個算法的核心在于通過輔助索引去查找時,將得到的主鍵進行排序,然后按照主鍵遞增的順序進行查找,對磁盤的讀接近順序讀,從而優(yōu)化性能
到底要不用Join
從上面的分析我們可以看到,用Join還是可行的,只要性能可控且在接受范圍內(nèi),還是能減少代碼復雜度的。需要避免的是join的表沒有索引,不然這樣的SQL發(fā)線上是災難性的。
總結
Join還是可以大膽的使用,只要把握好幾個原則:
1、盡量讓join的列是索引列,而且好是類型相同,盡可能是主鍵索引;
2、盡量將小表做驅(qū)動表(這一點MySQL在5.6某個版本后能自動完成);
3、養(yǎng)成將寫好的SQL進行explain的好習慣,觀察SQL的執(zhí)行過程。
看完上述內(nèi)容,你們對MySQL中Join的執(zhí)行過程有哪些有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。