热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Mysql中join连接算法和优化思路

查看SQL的explain的结果,如果Extra字段里面出现“BlockNestedLoop”即这时候sql查询使用BlockNested-LoopJoin算法&#x

查看SQL的explain的结果,如果Extra字段里面出现“Block Nested Loop” 即这时候sql查询使用Block Nested-Loop Join算法,就意味着连接表的字段没有索引,这时候性能很差。


在写SQL时,在join连接中应该遵循尽可能使用小表做为驱动表,驱动表指的就是left join语句左边的表和right join语句右边的表,如果SQL中没有指定join类型则是mysql根据表数据预估自动选择驱动表。



  • 1. 如果是IndexNested-Loop Join算法,应该选择小表做驱动表;
  • 2. 如果是Block Nested-Loop Join算法: 在join_buffer_size足够大的时候,是一样的; 在join_buffer_size不够大的时候(这种情况更常见),应该选择小表做驱动表。

通过下面的join语句分别分析一下几种join连接算法的过程和性能 


SELECT * FROM A LEFTJOIN B ON A.ID=B.NO 



Index Nested-LoopJoin

Index Nested-LoopJoin算法是join连接最优的join算法,如果使用join查询尽量使sql按照此算法执行才能保证性能。这个算法关键就在于检索过程中可以使用被驱动表的索引

如果上面sql中的B表的NO字段是索引字段,那么查询过程可以用上被驱动表的索引,这时候sql查询就可以使用Index Nested-LoopJoin算法。 由于时LEFT join所以表A是驱动表。

流程如下:


  • 1. 查询驱动表A中符合where条件的数据放入net_buffer,遍历读每一行数据 R;
  • 2. 从数据行R中,取出NO字段到表B里去查找,由于NO字段是索引所以走的是树搜索过程。NO值唯一的情况下每次的搜索过程都只扫描一行;
  • 3. 取出表B中满足条件的行,跟R组成一行,作为结果集的一部分;
  • 4. 如果net_buffer满了则返回客户端,清空buf后重复执行步骤1到3,直到表A的末尾循环结束 

如果不用join连接要实现同样的效果,通常就是拆分sql查询两次的方式

1.查询SELECT * FROM A

2.遍历1中的结果取出A.ID记为id

3.使用A.ID作为条件执行SELECT * FROM B where B.NO=id

4.重复执行3查询

上面的过程与上面Index Nested-LoopJoin算法的实现区别是sql执行了多次,多执行的次数取决于A表的行数。性能是不如Index Nested-LoopJoin算法的join连接的。


Block Nested-Loop Join

如果上面sql中的B表的NO字段不是索引,这时候sql查询使用Block Nested-Loop Join算法。

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


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

可以看到上面的流程相对于算法来说,扫描了B表全表导致性能差了很多。

不仅如此,当驱动表是大表时性能也会受到join_buffer的影响。join_buffer的大小是由参数join_buffer_size设定的,默认值是256k。

如果在执行上面的sql时,join_buffer中放不下表A的所有数 据话,就会分段放。这时候由于表A被分成了两次放入join_buffer中,导致表B会被扫描两次。


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


推荐阅读
  • 本文介绍了如何在MySQL中将零值替换为先前的非零值的方法,包括使用内联查询和更新查询。同时还提供了选择正确值的方法。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文介绍了在SQL中查询分组后每组行数的统计方法。通过使用count()函数和GROUP BY子句可以统计每组的行数,但是如何统计所有组的行数呢?本文提供了一种实现方法,并给出了相应的SQL查询语句。 ... [详细]
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文由编程笔记小编整理,介绍了PHP中的MySQL函数库及其常用函数,包括mysql_connect、mysql_error、mysql_select_db、mysql_query、mysql_affected_row、mysql_close等。希望对读者有一定的参考价值。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了通过mysql命令查看mysql的安装路径的方法,提供了相应的sql语句,并希望对读者有参考价值。 ... [详细]
  • ubuntu用sqoop将数据从hive导入mysql时,命令: ... [详细]
  • 如何在php中将mysql查询结果赋值给变量
    本文介绍了在php中将mysql查询结果赋值给变量的方法,包括从mysql表中查询count(学号)并赋值给一个变量,以及如何将sql中查询单条结果赋值给php页面的一个变量。同时还讨论了php调用mysql查询结果到变量的方法,并提供了示例代码。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • 本文介绍了使用postman进行接口测试的方法,以测试用户管理模块为例。首先需要下载并安装postman,然后创建基本的请求并填写用户名密码进行登录测试。接下来可以进行用户查询和新增的测试。在新增时,可以进行异常测试,包括用户名超长和输入特殊字符的情况。通过测试发现后台没有对参数长度和特殊字符进行检查和过滤。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • Oracle10g备份导入的方法及注意事项
    本文介绍了使用Oracle10g进行备份导入的方法及相关注意事项,同时还介绍了2019年独角兽企业重金招聘Python工程师的标准。内容包括导出exp命令、删用户、创建数据库、授权等操作,以及导入imp命令的使用。详细介绍了导入时的参数设置,如full、ignore、buffer、commit、feedback等。转载来源于https://my.oschina.net/u/1767754/blog/377593。 ... [详细]
author-avatar
手机用户2602890535
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有