一简介:参考了几位师兄,尤其是M哥大神的博客,让我恍然大悟,赶紧记录下
二 原理:
mysql的三种算法
1 Simple Nested-Loop Join
将驱动表/外部表的结果集作为循环基础数据,然后循环从该结果集每次一条获取数据作为下一个表的过滤条件查询数据,然后合并结果。如果有多表join,则将前面的表的结果集作为循环数据,取到每行再到联接的下一个表中循环匹配,获取结果集返回给客户端。
注意点:单条记录一条一条进行 比如C 表有N条记录去匹配D表 M 条记录那么要执行 NXM次,如果多表join,那么次数会更多
2 Block Nested-Loop Join
BNL优化,在join字段无索引的情况下
Block Nested-Loop Join对比Simple Nested-Loop Join多了一个中间处理的过程,也就是join buffer,使用join buffer将驱动表的查询JOIN相关列都给缓冲到了JOIN BUFFER当中,然后批量与非驱动表进行比较,这也来实现的话,可以将多次比较合并到一次,降低了非驱 动表的访问频率。也就是只需要访问一次S表。这样来说的话,就不会出现多次访问非驱动表的情况了,也只有这种情况下才会访问join buffer。
注意点:
1 此算法并非单条记录匹配,而是多条记录合并一起匹配,减少了匹配次数,提高了效率
2 此优化手段是在mysql5.5+版本开始出现,默认是打开状态
3 出现标识
explain生成解析树后出现 Using join buffer (Block Nested Loop) 连接字段无索引,但是利用了BNL优化了语句
4 能够被buffer的每一个join都会分配一个buffer, 也就是说一个query最终可能会使用多个join buffer
5 join buffer中只会保存参与join的列, 并非整个数据行。
6 只有在join类型为all, index, range的时候才可以使用join buffer。
3 Index Nested-Loop Join
这种算法在链接查询的时候,驱动表会根据关联字段的索引进行查找,当在索引上找到了符合的值,再回表进行查询,也就是只有当匹配到索引以后才会进行回表。至于驱动表的选择,MySQL优化器一般情况下是会选择记录数少的作为驱动表,但是当SQL特别复杂的时候不排除会出现错误选择。
注意点:
1 对于驱动表和非驱动表都有索引的情况下,会加速查找速度和减少匹配次数
2 最好采用自增长主键进行join字段,非唯一性索引会降低查询匹配速度,因为先要根据非唯一性索引定位主键,然后再进行查询
三 相关总结:
1 多表join查询要保证小结果集驱动大结果集作为优化选择
2 减少回表操作和匹配次数是算法的核心思想
3 多表join查询要保证连接join的字段都有索引
4 varchar作为主键进行连接查询是无法走索引的,会出现BNL优化(要特别注意)
5 对于无法走索引的join查询建议拆分或者更改条件
6 对于order by所选择的字段要尽量选用驱动表带索引字段
四 核心的东西来源于M哥的博客