MySQL中的 inner join 和 left join的區(qū)別解析(小結(jié)果集驅(qū)動大結(jié)果集)
場景描述
以一個場景為例:
單據(jù)A:下游子表 (數(shù)據(jù)量級?。?br />單據(jù)B:下游主表(數(shù)據(jù)量級小)
單據(jù)C:中游子表(數(shù)據(jù)量級?。?br />單據(jù)D:中游主表(數(shù)據(jù)量級?。?br />單據(jù)E:上游子表(數(shù)據(jù)量級?。?br />單據(jù)F:上游主表(比其他表數(shù)據(jù)量級大)
需求:將單據(jù)F的某個字段,刷到單據(jù)A的某個字段上面。從A到F,都可以通過id連接索引的形式,來關(guān)聯(lián)。但是A到F的連接順序必須是從A到F順序連接。比如:
這幾個表的連接可以用下面的例子演示:
a join b on a.id = b.id b join c on b.id = c.mainId c join d on c.id = d.tableId d join e on d.id = e.tid e join f on e.tid = f.code
inner join 和 left join 的區(qū)別
我們寫update語句的時候,肯定是想要用join連表的。但是到底是使用inner join;還是left join比較好呢?
- left join:
select a.*,b.* from a left join b on a.id = b.id
, 這兩個表連接,根據(jù)后面的on條件,如果b表里面的b.id不符合 a.id = b.id ,那么a表里面的所有數(shù)據(jù)列都會給展示出來。然后b表沒有這種數(shù)據(jù),所以sql里面的 b.* 會被全部填充成null
- inner join:
select a.*,b.* from a inner join b on a.id = b.id
, 這兩個表連接,根據(jù)后面on條件,如果b表里面的b.id不符合 a.id = b.id ,那么a表里面的部分數(shù)據(jù)列(不符合a.id = b.id條件的)就不會展示。
根據(jù)上面的定義,left join常用于select 語句;這是為了防止a表會少一些匹配記錄,為了能展示全a表,所以使用left join。
如下圖所示:
索引角度理解小結(jié)果集驅(qū)動大結(jié)果集
不管是 left join 和 inner join,都要注意小結(jié)果集驅(qū)動大結(jié)果集。a表 join b表的時候,
還是看之前例子的SQL:
select a.*,b.* from a left join b on a.id = b.id
假設(shè)a表數(shù)量級是100萬條,b表數(shù)量級是100條。我這樣連接,就是大表驅(qū)動小表;直接看查找次數(shù):
在用后面on條件連接兩個表的時候,首先要走B+樹索引進行匹配;拿a表這100w的數(shù)量級,逐條對比 -> B+樹 -> 匹配到 b表的記錄。假設(shè)B+樹查找b表的100條要用2次查找,那么最終查找次數(shù)就是: 100萬 * 2 次
如果是小表驅(qū)動大表:
select a.*,b.* from b left join a on a.id = b.id
那么就會拿b表這100條,逐條對比 -> B+樹 -> 匹配到 a表的記錄。假設(shè)B+樹查找a表的100w條要用3次查找,那么最終查找次數(shù)就是: 100 * 3 次
從索引匹配的角度講,小結(jié)果集驅(qū)動大結(jié)果集的效率優(yōu)化了不是一點半點。我們要有意識地讓小表在左邊,大表在右邊
但是如果你用的是inner join,MySQL內(nèi)部會做優(yōu)化,自動讓小表在前大表在后。也就是說你怎么寫,效率都是一樣的。但是left join卻不能自動優(yōu)化,這點需要注意!
update語句常用 inner join而不是left join
舉例如下SQL:
(任務(wù)目標:用f 表字段更新a表字段)
update a inner join b on a.id = b.id inner join c on b.id = c.mainId inner join d on c.id = d.tableId inner join e on d.id = e.tid inner join f on e.tid = f.code set a.Demand_orgid = f.req_org_id where xxx = xxx;
update 原則上 都得用inner join。
看上面的SQL,假設(shè)你全部都用的left join做關(guān)聯(lián),由于你最終update 的是 a的字段;假設(shè)a表在left join的過程中,因為某個點匹配不到f表,那么用f 表字段更新a表字段 這一個過程中,一旦有任意一個環(huán)節(jié)匹配不到,那么f 表的字段全都會用null填充。最終,a表匹配不到f表的數(shù)據(jù),都會被更新成null !
但是如果你用inner join,用f 表字段更新a表字段 這一個過程中,一旦有任意一個環(huán)節(jié)匹配不到,那么a表匹配不到 f 表的所有數(shù)據(jù)就不會顯示,也就是說不會更新。
你想想,你都匹配不到數(shù)據(jù)列。你還更新啥,難道更新null嗎。基于上面的原因,inner join 其實就滿足需求了
況且!left join 要考慮這幾張表的大小關(guān)系,誰大誰小,小結(jié)果集驅(qū)動大結(jié)果集。但是inner join 就完全不用考慮此問題,因為inner join MySQL內(nèi)部會做優(yōu)化,自動讓小表在前大表在后。
到此這篇關(guān)于MySQL中的 inner join 和 left join的區(qū)別的文章就介紹到這了,更多相關(guān)mysql inner join 和 left join區(qū)別內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Windows下mysql 5.7 設(shè)置區(qū)分大小寫(敏感),設(shè)置默認編碼 utf8mb4
最近需要將Windows下的mysql 5.7設(shè)置區(qū)分大小寫(敏感),設(shè)置默認編碼 utf8mb4,需要的朋友可以參考下2022-10-10淺談mysql使用limit分頁優(yōu)化方案的實現(xiàn)
在mysql中l(wèi)imit可以實現(xiàn)快速分頁,但是如果數(shù)據(jù)到了幾百萬時我們的limit必須優(yōu)化才能有效的合理的實現(xiàn)分頁了,否則可能卡死你的服務(wù)器哦。感興趣的可以一起來了解一下如何實現(xiàn)優(yōu)化2018-12-12mysql 5.7.17 winx64解壓版安裝配置方法圖文教程
這篇文章主要為大家詳細介紹了mysql 5.7.17 winx64解壓版安裝配置方法圖文教程,具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-06-06