[Mysql]Join

极客时间关于Join

 

straight_join 让 MySQL 使用固定的连接方式执行查询,这样优化器只会按照我们指定的方式去 join

嵌套查询类似,并且可以用上被驱动表的索引,所以我们称之为“Index Nested-Loop Join”,简称 NLJ。

NLJ - 嵌套查询join

[Mysql]Join

都有索引扫描行数很少,T1表全表的行数 + T2表的有索引只走一行扫描。所以很少扫描次数。

使用JOIN也是有好处的

驱动表是走全表扫描,而被驱动表是走树搜索。

N 对扫描行数的影响更大,因此应该让小表来做驱动表。

使用 join 语句,性能比强行拆成多个单表执行 SQL 语句的性能要好;如果使用 join 语句的话,需要让小表做驱动表。

这个结论的前提是“可以使用被驱动表的索引”。

 

Simple Nested-Loop Join

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

把表 t1 的数据读入线程内存 join_buffer 中,由于我们这个语句中写的是 select *,因此是把整个表 t1 放入了内存;扫描表 t2,把表 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回。

 

扫描行数变少,在内存中会做Join buffer中做判断。所以驱动表要选小表。

join_buffer 的大小是由参数 join_buffer_size 设定的,默认值是 256k。如果放不下表 t1 的所有数据话,策略很简单,就是分段放。我把 join_buffer_size 改成 1200,再执行

执行过程就变成了:

  1. 扫描表 t1,顺序读取数据行放入 join_buffer 中,放完第 88 行 join_buffer 满了,继续第 2 步;
  2. 扫描表 t2,把 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回;
  3. 清空 join_buffer;
  4. 继续扫描表 t1,顺序读取最后的 12 行数据放入 join_buffer 中,继续执行第 2 步。

所以也就是分段去做这个事情,如果Joinbuffer满了。