Index Nested-Loop Join
在形式上,可以用上被驱动表的索引,称之为“Index Nested-Loop Join”,简称 NLJ。使用 join 语句,性能比强行拆成多个单表执行 SQL 语句的性能要好;如果使用 join 语句的话,需要让小表做驱动表。
Simple Nested-Loop Join
被驱动表没有索引,N*M极其笨重,MySQL不会使用,而是使用下面的算法。
Block Nested-Loop Join
#STRAIGHT_JOIN is similar to JOIN, except that the left table is always read before the right table.#慎重使用,因为大部分情况下指定的执行顺序并不一定会比优化引擎要靠谱。select * from t1 straight_join t2 on (t1.a=t2.b);
1.把表t1的数据读入线程内存 join_buffer 中,由于这个语句中写的是 select *,因此是把整个表 t1 放入了内存;
2.扫描表 t2,把表 t2 中的每一行取出来,跟 join_buffer 中的数据做对比,满足 join 条件的,作为结果集的一部分返回。
从时间复杂度上来说,与Simple Nested-Loop Join算法是一样的。但是,Block Nested-Loop Join 算法的这 10 万次判断是内存操作,速度上会快很多,性能也更好。join_buffer 的大小是由参数 join_buffer_size 设定的,默认值是 256k。如果放不下表 t1 的所有数据话,策略很简单,就是分段放。如果你的 join 语句很慢,就把 join_buffer_size 改大。
在决定哪个表做驱动表的时候,应该是两个表按照各自的条件过滤,过滤完成之后,计算参与 join 的各个字段的总数据量,数据量小的那个表,就是“小表”,应该作为驱动表。
小结
如果可以使用被驱动表的索引,join 语句还是有其优势的;
不能使用被驱动表的索引,只能使用 Block Nested-Loop Join 算法,这样的语句就尽量不要使用;
在使用 join 的时候,应该让小表做驱动表。
参考资料:丁奇,MySQL实战45讲
部分内容来自网络,如有侵权请联系作者删除。




