MySql 你知道什么情況下適合使用Join 聯(lián)表查詢嗎 ?
志在巔峰的攀登者,不會陶醉在沿途的某個腳印之中。
如下我這里有兩張表,表t1為某活動的報名信息表,部分建表 DDL 如下

表t2為 投票信息表,也就是說 t2表中保存的是給t1表中的報名用戶投票記錄信息,部分建表 DDL 如下:

現(xiàn)在 我 t1 表中有 10 條數(shù)據(jù)

t2表中 84 條數(shù)據(jù),如圖所示

現(xiàn)在有一需求就是查詢 戶的投票記錄以及報名信息,那么我們需要從 t1表中獲取報名信息,然后再從t2表中獲取每個用戶的投票記錄。
那么無非就是有兩種查詢思維,一種是先取t1,再循環(huán)取t2,另一種是使用 join ,那到底使用哪種,你是怎么決定的呢???
1 我們先來看看 循環(huán)查詢
在不使用join的情況下,我們需要先從t1表中查出這用戶的報名信息,然后循環(huán)從t2表中查詢投票信息,這個過程如下
執(zhí)行select * from t1 ,每一行數(shù)據(jù)記為 C,這一步會對t1表進行全表掃描,我們t1表中是10條數(shù)據(jù),全表掃描10行

type = ALL,全表掃描,MYSQL掃描全表來找到匹配的行
然后循環(huán)遍歷這 10 行數(shù)據(jù),從每一行 數(shù)據(jù) C 中取出字段 id 的值; 執(zhí)行select * from t2 where activity_user_id=id;(activity_user_id走的是索引樹搜索) 把返回的結(jié)果和 C 構(gòu)成結(jié)果集的一行。
在表t2中,滿足 t1表中id為12的有49條數(shù)據(jù)

這個過程中 掃描 49行數(shù)據(jù)

type = ref ,使用非唯一性索引或者唯一索引的前綴掃描,返回匹配某個單獨值的記錄行。
滿足 id 為13的有 35條數(shù)

這個過程中掃描35行數(shù)據(jù)

然后 t1 表中其他 8條數(shù)據(jù)在表 t2中沒有記錄,所以查詢過程中各掃描一行。
在這個過程中,這樣查詢下來,需要在業(yè)務(wù)代碼中自己組裝循環(huán)查詢,t1表掃描 10行,t2表掃描 35 + 49 + 8 = 92,查詢完成總共掃描 102行數(shù)據(jù)。
2 使用 join 時
當(dāng)使用 join 時,可以這樣寫 :(使用 STRAIGHT_JOIN 保證固定聯(lián)表順序)

滿足條件的有 84 條數(shù)據(jù)

這個語句的執(zhí)行流程是這樣的:
第一步 從表 t1 中讀入一行數(shù)據(jù) C;
第二步從數(shù)據(jù)行 C 中,取出 id 字段到表 t2 的 activity_user_id 索引樹中搜索;
第三步 取出表 t2 中滿足條件的行,跟 C 組成一行,作為結(jié)果集的一部分;
第四步 重復(fù)執(zhí)行步驟 1 到 3,直到表 t1 的末尾循環(huán)結(jié)束。

這個過程是先遍歷表 t1,然后根據(jù)從表 t1 中取出的每行數(shù)據(jù)中的 id 值,去表 t2 中查找滿 足條件的記錄,這個過程稱為 “Index Nested-Loop Join”,簡稱 NLJ。
在這個過種中,t1表是驅(qū)動表,是走全表掃描,t2是被驅(qū)動表,是走樹搜索,所以在 join過程中,應(yīng)該讓小表作驅(qū)動表。
此時 我們將 t2表中的 activity_user_id 索引刪除

我們再查詢一下

我們可以清楚的看到當(dāng)不走索引搜索時,t1與t2都走了全表掃描,
執(zhí)行過程如下
第一步掃描表 t1,順序讀取數(shù)據(jù)行放入 join_buffer 中,假設(shè)放完第 3 行 join_buffer 滿了,繼續(xù) 第二步操作;
第二步 掃描表 t2,把 t2 中的每一行取出來,跟 join_buffer 中的數(shù)據(jù)做對比,滿足 join 條件的,作為結(jié)果集的一部分返回;
第三步 清空 join_buffer;
第四步 繼續(xù)掃描表 t1,順序讀取最后的 7 行數(shù)據(jù)放入 join_buffer 中,繼續(xù)執(zhí)行第 二 步。
這時候由于表 t1 被分成了兩次放入 join_buffer 中,導(dǎo)致表 t2 會被掃描兩次,這個過程就是 “Block Nested-Loop Join”。
顯然 這兩種情況 “Index Nested-Loop Join” 與 “Block Nested-Loop Join” 分析得出,如果可以使用到被驅(qū)動表中的索引,就可以使用 join 來查詢。
如果無法使用到被驅(qū)動表的索引查詢,這樣可能要掃描被驅(qū)動表很多次,會占用大量的系統(tǒng)資源,所以這種情況下 join 盡量不要用。
完畢
不局限于思維,不局限語言限制,才是編程的最高境界。