mysql对多表关联查询使用Nested-Loop Join算法,简单总结就是通过驱动表作为入口,一层层的往内部查询,驱动表的数据量对查询效率很关键。
而对驱动表的选择,from后的表顺序并不起决定作用,mysql会根据多重因素选择最优的链接顺序。如果想自行控制链接顺序可以通过Optimizer Hints(mysql 8.0)指定。
使用saklia数据库
1.先通过一个left join的例子说明from后的表顺序对实际执行时的关联顺序不起决定作用的现象
explain
select a.rental_id, a.rental_date,b.film_id
from rental a left join inventory b on a.inventory_id = b.inventory_id
可以看到执行顺序是a>b
2.接下来,我们调换一下表的顺序
explain
select a.rental_id, a.rental_date,b.film_id
from inventory b left join rental a on a.inventory_id = b.inventory_id
从explain输出结果看,b确实到前面去了,变成了b>a
3.还没结束接着看,我们带上a的一个条件
explain
select a.rental_id, a.rental_date,b.film_id
from inventory b left join rental a on a.inventory_id = b.inventory_id
where a.rental_date >= '2005-01-19 02:18:51';
看到顺序又变成了a>b,此sql并未改变from表的顺序,只是增加了a的过滤条件
4.如果就是想将b放到第一个驱动表的位置,可以通过Optimizer Hints的JOIN_PREFIX指定
explain
select /*+JOIN_PREFIX(b) */ a.rental_id, a.rental_date,b.film_id
from inventory b left join rental a on a.inventory_id = b.inventory_id
where a.rental_date >= '2005-01-19 02:18:51';
不过JOIN_PREFIX只有mysql8.0才有,5.7并没有。除了JOIN_PREFIX还有JOIN_FIXED_ORDER、JOIN_ORDER、JOIN_SUFFIX用来指定表链接顺序
更多Optimizer Hints信息可到官网查看https://dev.mysql.com/doc/refman/8.0/en/optimizer-hints.html