【MySQL学习】No.4 Join语句执行

```

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。

它对应的流程图如下所示:


图片发自App

在这个流程里:

对驱动表 t1 做了全表扫描,这个过程需要扫描 100 行;

而对于每一行 R,根据 a 字段去表 t2 查找,走的是树搜索过程。由于构造的数据都是一一对应的,因此每次的搜索过程都只扫描一行,也是总共扫描 100 行;

所以,整个执行流程,总扫描行数是 200。

你可能感兴趣的:(【MySQL学习】No.4 Join语句执行)