子查询与连接查询 执行过程与效率对比

连接查询

一.Nested-Loop Join
在Mysql中,使用Nested-Loop Join的算法思想去优化join,Nested-Loop Join翻译成中文则是“嵌套循环连接”。

举个例子:
select * from t1 inner join t2 on t1.id=t2.tid
(1)t1称为外层表,也可称为驱动表。
(2)t2称为内层表,也可称为被驱动表。

//伪代码表示:
List result = new ArrayList<>();
for(Row r1 in List t1){
    for(Row r2 in List t2){
        if(r1.id = r2.tid){
            result.add(r1.join(r2));
        }
    }
}
在Mysql的实现中,Nested-Loop Join有3种实现的算法:

Simple Nested-Loop Join:SNLJ,简单嵌套循环连接
Index Nested-Loop Join:INLJ,索引嵌套循环连接
Block Nested-Loop Join:BNLJ,缓存块嵌套循环连接
在选择Join算法时,会有优先级,理论上会优先判断能否使用INLJ、BNLJ:
Index Nested-LoopJoin > Block Nested-Loop Join > Simple Nested-Loop Join

二.Simple Nested-Loop
简单嵌套循环连接实际上就是简单粗暴的嵌套循环,如果table1有1万条数据,table2有1万条数据,那么数据比较的次数=1万 * 1万 =1亿次,这种查询效率会非常慢。

所以Mysql继续优化,然后衍生出Index Nested-LoopJoin、Block Nested-Loop Join两种NLJ算法。在执行join查询时mysql会根据情况选择两种之一进行join查询。
三.Index Nested-LoopJoin(减少内层表数据的匹配次数)
索引嵌套循环连接是基于索引进行连接的算法,索引是基于内层表的,通过外层表匹配条件直接与内层表索引进行匹配,避免和内层表的每条记录进行比较, 从而利用索引的查询减少了对内层表的匹配次数,优势极大的提升了 join的性能:
原来的匹配次数 = 外层表行数 * 内层表行数
优化后的匹配次数= 外层表的行数 * 内层表索引的高度(B+数的平均时间复杂度logn)

使用场景:只有内层表join的列有索引时,才能用到Index Nested-LoopJoin进行连接。
由于用到索引,如果索引是辅助索引而且返回的数据还包括内层表的其他数据,则会回内层表查询数据,多了一些IO操作。

四.Block Nested-Loop Join(减少内层表数据的循环次数)
缓存块嵌套循环连接通过一次性缓存多条数据,把参与查询的列缓存到Join Buffer 里,然后拿join buffer里的数据批量与内层表的数据进行匹配,从而减少了内层循环的次数(遍历一次内层表就可以批量匹配一次Join Buffer里面的外层表数据)。
当不使用Index Nested-Loop Join的时候,默认使用Block Nested-Loop Join。

什么是Join Buffer?
(1)Join Buffer会缓存所有参与查询的列而不是只有Join的列。
(2)可以通过调整join_buffer_size缓存大小
(3)join_buffer_size的默认值是256K,join_buffer_size的最大值在MySQL 5.1.22版本前是4G-1,而之后的版本才能在64位操作系统下申请大于4G的Join Buffer空间。
(4)使用Block Nested-Loop Join算法需要开启优化器管理配置的optimizer_switch的设置block_nested_loop为on,默认为开启。

相关子查询和不相关子查询 

相关子查询:

比如

select t.id,t.name,t.pass from student t where 80<=(select f.score from f
 where f.id=t.id and f.name='xxx') 
这就是1个相关子查询,可以理解为2层循环,要想执行内层的查询,需要先从外层查询到1个值出来。

执行的顺序是,父查询1个值,子查询对这个得到的值进行1轮查询,总查询次数是m*n

因为子查询需要父查询的结果才能执行,所以叫相关子查询

不相关子查询:

比如:

select t.id,t.name,t.pass from t where t.id in (select f.id from  f where f.score=70) 
这就是1个不相关子查询,子查询的不需要父查询把结果传进来,所以叫不相关子查询

执行顺序是子查询先执行,得到结果后传给父查询,父查询就不用每次查询完1个值后再执行1轮子查询

由于2个查询是分开的,无关联的,所以叫不相关子查询,查询次数是m+n

 

参考:

链接:https://blog.csdn.net/u010841296/article/details/89790399

链接:https://blog.csdn.net/wzngzaixiaomantou/article/details/81807399

你可能感兴趣的:(MySQL)