久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL中Join的執(zhí)行過程有哪些

202次閱讀
沒有評論

共計 1926 個字符,預計需要花費 5 分鐘才能閱讀完成。

自動寫代碼機器人,免費開通

今天就跟大家聊聊有關 MySQL 中 Join 的執(zhí)行過程有哪些,可能很多人都不太了解,為了讓大家更加了解,丸趣 TV 小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

MySQL 的 Join 是如何執(zhí)行的

join 可以說一種集合的運算,比如 left join,right join,inner join,full join,outer join,cross join 等,這些集合間的計算關系對應在高中數(shù)學集合里面的交集,并集,補集,全集等。但在實際的代碼中,join 運算基本上是通過多層循環(huán)來實現(xiàn)的。

舉一個例子,假設有 t1,t2 兩張表,表結(jié)構(gòu)分別如下:

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 組成一行,作為結(jié)果集的一部份

重復執(zhí)行步驟 1,2,3, 直到表 t1 的所以數(shù)據(jù)循環(huán)完畢

基本上先遍歷 t,1, 然后根據(jù) t1 中的每行數(shù)據(jù)中的 username,去表 t2 中查找滿足條件的記錄。基本就是 2 層循環(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ù)存儲結(jié)構(gòu)為二叉樹,時間復雜度為 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)為順序讀,因為二叉樹的存儲結(jié)構(gòu),每次非主鍵查找,有一個回表的動作,即根據(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ā)線上是災難性的。

總結(jié)

Join 還是可以大膽的使用,只要把握好幾個原則:

1、盡量讓 join 的列是索引列,而且最好是類型相同, 盡可能是主鍵索引;

2、盡量將小表做驅(qū)動表 (這一點 MySQL 在 5.6 某個版本后能自動完成);

3、養(yǎng)成將寫好的 SQL 進行 explain 的好習慣,觀察 SQL 的執(zhí)行過程。

看完上述內(nèi)容,你們對 MySQL 中 Join 的執(zhí)行過程有哪些有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注丸趣 TV 行業(yè)資訊頻道,感謝大家的支持。

向 AI 問一下細節(jié)

正文完
 
丸趣
版權(quán)聲明:本站原創(chuàng)文章,由 丸趣 2023-12-04發(fā)表,共計1926字。
轉(zhuǎn)載說明:除特殊說明外本站除技術相關以外文章皆由網(wǎng)絡搜集發(fā)布,轉(zhuǎn)載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 新乡县| 无极县| 怀仁县| 宜春市| 兴和县| 北票市| 武宁县| 瑞安市| 博客| 萍乡市| 金坛市| 宾川县| 黄石市| 屯昌县| 杭锦旗| 德钦县| 营山县| 石林| 白水县| 德安县| 哈密市| 平阴县| 忻城县| 安化县| 武邑县| 潼南县| 西宁市| 康保县| 错那县| 恩平市| 胶州市| 武宁县| 湖南省| 扬中市| 鹤峰县| 拉萨市| 岢岚县| 图片| 正镶白旗| 新建县| 高陵县|