```
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 行数据,在表 t1 里插入的是 100 行数据。
```
select * from t1 straight_join t2 on (t1.a=t2.a);
```
如果直接使用 join 语句,MySQL 优化器可能会选择表 t1 或 t2 作为驱动表,这样会影响分析 SQL 语句的执行过程。为了便于分析执行过程中的性能问题,改用 straight_join 让 MySQL 使用固定的连接方式执行查询,这样优化器只会按照指定的方式去 join。在这个语句里,t1 是驱动表,t2 是被驱动表。
被驱动表 t2 的字段 a 上有索引,join 过程用上了这个索引,因此这个语句的执行流程是这样的:
从表 t1 中读入一行数据 R;
从数据行 R 中,取出 a 字段到表 t2 里去查找;
取出表 t2 中满足条件的行,跟 R 组成一行,作为结果集的一部分;
重复执行步骤 1 到 3,直到表 t1 的末尾循环结束。
这个过程是先遍历表 t1,然后根据从表 t1 中取出的每行数据中的 a 值,去表 t2 中查找满足条件的记录。在形式上,这个过程跟嵌套查询类似,并且可以用上被驱动表的索引,所以称之为“Index Nested-Loop Join”,简称 NLJ。
它对应的流程图如下所示:
【MySQL学习】No.4 Join语句执行在这个流程里:
对驱动表 t1 做了全表扫描,这个过程需要扫描 100 行;
而对于每一行 R,根据 a 字段去表 t2 查找,走的是树搜索过程。由于构造的数据都是一一对应的,因此每次的搜索过程都只扫描一行,也是总共扫描 100 行;
所以,整个执行流程,总扫描行数是 200。
网友评论