MySQL-join语句

MySQL 执行 join 语句的两种可能算法,这两种算法是由能否使用被驱动表的索引决定的。而能否用上被驱动表的索引,对 join 语句的性能影响很大。

目录

一、指定驱动表

二、join语句的两种算法

1、被驱动表t2的条件字段用上了索引

2、被驱动表t2的条件字段没有索引 (join_buffer)

3、选择【小表】作为驱动表,小表指什么


一、指定驱动表

直接使用 join 语句,MySQL 优化器可能会选择表 t1 或 t2 作为驱动表,用 【straight_join 】让 MySQL 使用固定的连接方式执行查询,来指定join顺序。

以下sql,指定了t1来做驱动表,t2是被驱动表

select * from t1 straight_join t2 on (t1.a=t2.a);

left join 和 right join :

不会强制强制指定驱动表,但是由于语义的关系,大概率上是按照语句上写的关系去驱动,效率是比较高的。

二、join语句的两种算法

创建两个表,这两个表都有一个主键索引 id 和一个索引 a,字段 b 上无索引。存储过程 idata() 往表 t2 里插入了 1000 行数据,在表 t1 里插入的是 100 行数据。

1、被驱动表t2的条件字段用上了索引

select * from t1 straight_join t2 on (t1.a=t2.a);
  1. 从表 t1 中读入一行数据 R;
  2. 从数据行 R 中,取出 a 字段到表 t2 里去查找;取出表 t2 中满足条件的行,跟 R 组成一行,作为结果集的一部分;
  3. 重复执行步骤 1 到 3,直到表 t1 的末尾循环结束。

这个过程是先遍历表 t1,然后根据从表 t1 中取出的每行数据中的 a 值,去表 t2 中查找满足条件的记录。

在这个 join 语句执行过程中,驱动表是走全表扫描,而被驱动表是走树搜索。[让小表做驱动表]

2、被驱动表t2的条件字段没有索引 (join_buffer)

select * from t1 straight_join t2 on (t1.a=t2.b);

由于表 t2 的字段 b 上没有索引,因此再用图 2 的执行流程时,每次到 t2 去匹配的时候,就要做一次全表扫描。

被驱动表上没有可用的索引,算法的流程是这样的:

  1. 把表 t1 的数据读入线程内存 join_buffer 中,由于我们这个语句中写的是 select *,因此是把整个表 t1 放入了内存;
  2. 扫描表 t2,把表 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回。join_buffer_size 越大,一次可以放入的行越多,分成的段数也就越少,对被驱动表的全表扫描次数就越少。

对表 t1 和 t2 都做了一次全表扫描,因此总的扫描行数是 1100。由于 join_buffer 是以无序数组的方式组织的,因此对表 t2 中的每一行,都要做 100 次判断,总共需要在内存中做的判断次数是:100*1000=10 万次。[选择小表做驱动表]

3、选择【小表】作为驱动表,小表指什么

在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与 join 的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。

MySQL实战-34

 

猜你喜欢

转载自blog.csdn.net/u013025748/article/details/114859040
今日推荐