```
CREATE TABLE `t2` (
? `id` int(11) NOT NULL,
? `a` int(11) DEFAULT NULL,
? `b` int(11) DEFAULT NULL,
? PRIMARY KEY (`id`),
? KEY `a` (`a`)
) ENGINE=InnoDB;
drop procedure idata;
delimiter ;;
create procedure idata()
begin
? declare i int;
? set i=1;
? while(i<=1000)do
? ? insert into t2 values(i, i, i);
? ? set i=i+1;
? end while;
end;;
delimiter ;
call idata();
create table t1 like t2;
insert into t1 (select * from t2 where id<=100)
```
可以看到宠进,這兩個表都有一個主鍵索引 id 和一個索引 a桥胞,字段 b 上無索引寺庄。存儲過程 idata() 往表 t2 里插入了 1000 行數(shù)據(jù)病附,在表 t1 里插入的是 100 行數(shù)據(jù)离福。
```
select * from t1 straight_join t2 on (t1.a=t2.a);
```
如果直接使用 join 語句,MySQL 優(yōu)化器可能會選擇表 t1 或 t2 作為驅(qū)動表趴久,這樣會影響分析 SQL 語句的執(zhí)行過程悯周。為了便于分析執(zhí)行過程中的性能問題,改用 straight_join 讓 MySQL 使用固定的連接方式執(zhí)行查詢杆烁,這樣優(yōu)化器只會按照指定的方式去 join牙丽。在這個語句里,t1 是驅(qū)動表兔魂,t2 是被驅(qū)動表烤芦。
被驅(qū)動表 t2 的字段 a 上有索引,join 過程用上了這個索引析校,因此這個語句的執(zhí)行流程是這樣的:
從表 t1 中讀入一行數(shù)據(jù) R构罗;
從數(shù)據(jù)行 R 中,取出 a 字段到表 t2 里去查找智玻;
取出表 t2 中滿足條件的行遂唧,跟 R 組成一行,作為結(jié)果集的一部分吊奢;
重復執(zhí)行步驟 1 到 3盖彭,直到表 t1 的末尾循環(huán)結(jié)束。
這個過程是先遍歷表 t1页滚,然后根據(jù)從表 t1 中取出的每行數(shù)據(jù)中的 a 值召边,去表 t2 中查找滿足條件的記錄。在形式上裹驰,這個過程跟嵌套查詢類似隧熙,并且可以用上被驅(qū)動表的索引,所以稱之為“Index Nested-Loop Join”幻林,簡稱 NLJ贞盯。
它對應(yīng)的流程圖如下所示:
在這個流程里:
對驅(qū)動表 t1 做了全表掃描,這個過程需要掃描 100 行沪饺;
而對于每一行 R邻悬,根據(jù) a 字段去表 t2 查找,走的是樹搜索過程随闽。由于構(gòu)造的數(shù)據(jù)都是一一對應(yīng)的,因此每次的搜索過程都只掃描一行肝谭,也是總共掃描 100 行掘宪;
所以蛾扇,整個執(zhí)行流程,總掃描行數(shù)是 200魏滚。