Mysql表连接的执行流程详解

 更新时间:2022年08月25日 11:37:14   作者:Balloon​​​​​​​  
这篇文章主要介绍了Mysql表连接的执行流程详解,文章围绕主题展开详细的内容介绍,具有一定的参考价值,需要的小伙伴可以参考一下,希望对你的学习有所帮助

1. 前言

对于连接操作,驱动表和被驱动表的关联条件我们放在on后面,如果额外增加对驱动表和被驱动表的过滤条件,放到on或者where后面都不会报错,但是得到的结果集却是不一样的???

1.1 mysql连接的原理

众所周知,mysql是基于嵌套循环连接(Nested-Loop Join,暂不考虑优化算法)算法来进行表之间的连接操作的,大致过程如下:

  • 选取驱动表,使用与驱动表相关的过滤条件执行对驱动表的单表查询;
  • 对于查询到的驱动表中的每一条纪录,分别到被驱动表中查找匹配的纪录。

伪代码如下:

for each row in t1 {      // 遍历满足对t1单表查询结果集中的每一条纪录
    for each row in t2 {  // 对于某条t1纪录,遍历满足对t2单表查询结果集中的每一条纪录
        if row satisfies join conditions, send to client
    }
}

1.2 show warnings命令

我们写的sql语句,在经过优化器优化后才会交给执行器执行,而show warnings命令则可以帮助我们获得优化器优化后的sql。

2. 准备工作

表结构如下:

CREATE TABLE `student` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `stu_code` varchar(20) NOT NULL DEFAULT '',
  `stu_name` varchar(30) NOT NULL DEFAULT '',
  `stu_sex` varchar(10) NOT NULL DEFAULT '',
  `stu_age` int(10) NOT NULL DEFAULT '0',
  `stu_dept` varchar(30) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE KEY `uq_stu_code` (`stu_code`)
) ENGINE=InnoDB AUTO_INCREMENT=43 DEFAULT CHARSET=utf8mb4

CREATE TABLE `course` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `cou_code` varchar(20) NOT NULL DEFAULT '',
  `cou_name` varchar(50) NOT NULL DEFAULT '',
  `cou_score` int(10) NOT NULL DEFAULT '0',
  `stu_code` varchar(20) NOT NULL DEFAULT '',
  PRIMARY KEY (`id`) USING BTREE,
  KEY `idx_stu_code_cou_code` (`stu_code`,`cou_code`)
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4

表数据如下: 

3. inner join内连接on、where的区别

sql如下:

select * from student
inner join course on student.stu_code = course.stu_code
and student.stu_code >= 3 and course.cou_score >= 80;

执行explain+sql命令: 

执行show warnings命令: 

分析:从show warnings分析来看,对于inner join连接,经过优化器优化后,on连接条件会转化为where!也就是说内连接中的where和on是等价的

4. left join左连接on、where的区别

4.1 where驱动表过滤条件

sql如下:

select * from student
left join course on student.stu_code = course.stu_code
where student.stu_code >= 3;

执行explain+sql命令: 

执行show warnings命令: 

结果集: 

分析:从explain分析看出,student作为驱动表,把student.stu_code >= 3作为过滤条件进行全表扫描,然后把查询到的每条纪录的student.stu_code(也就是on条件里面的)分别作为过滤条件让被驱动表course做单表查询。

4.2 on驱动表过滤条件

sql如下:

select * from student
left join course on student.stu_code = course.stu_code 
and student.stu_code >= 3;

执行explain+sql命令: 

执行show warnings命令: 

结果集: 

从结果集来看,student.stu_code >= 3并未生效,为什么?

分析:从explain分析看出,student作为驱动表,做全表扫描,然后把查询到的每条记录的student.stu_code和student.stu_code >= 3(也就是on条件里面的)分别做为过滤条件让被驱动表做单表查询;此时student.stu_code >= 3对驱动表是不过滤的,仅在连接被驱动表时生效,查询不到符合纪录而返回NULL!

4.3 on被驱动表过滤条件

sql如下:

select * from student
left join course on student.stu_code = course.stu_code 
and course.cou_score >= 80;

执行explain+sql命令: 

执行show warnings命令: 

结果集: 

分析:从explain分析看出,student作为驱动表,做全表扫描,然后把查询到的每条记录的student.stu_code和course.cou_score >= 80(也就是on条件里面的)分别做为过滤条件让被驱动表做单表查询;

4.4 where被驱动表过滤条件

sql如下: 

执行explain+sql命令: 

执行show warnings命令: 

结果集: 

从show warnings分析来看?left join连接变成了inner join连接?

分析:从show warnings分析看出,如果被驱动表有过滤条件在where,那么left join会被失效,被优化成inner join连接。所以被驱动表的过滤条件应该放在on而不是where

5. 总结

其实,在内连接的基础上引入外连接的概念,就是为了解决驱动表中的纪录即使没有在被驱动表中找到匹配的纪录,仍要加入结果集的问题。所以对于外连接(外连接包括:左连接、右连接),被驱动表的过滤条件我们应该放在on!

到此这篇关于Mysql表连接的执行流程详解的文章就介绍到这了,更多相关Mysql表连接 内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL5绿色版windows下安装总结(推荐)

    MySQL5绿色版windows下安装总结(推荐)

    这篇文章主要介绍了MySQL5绿色版windows下安装总结,需要的朋友可以参考下
    2017-03-03
  • 提高MySQL 查询效率的三个技巧

    提高MySQL 查询效率的三个技巧

    MySQL由于它本身的小巧和操作的高效, 在数据库应用中越来越多的被采用.我在开发一个P2P应用的时候曾经使用MySQL来保存P2P节点,由于P2P的应用中,结点数动辄上万个,而且节点变化频繁,因此一定要保持查询和插入的高效.以下是我在使用过程中做的提高效率的三个有效的尝试. 1. 使用statement进行绑定查询 2. 随机的获取记录 3. 使用连接池管理连接.
    2008-04-04
  • 数据库中update与delete使用表别名的深入研究

    数据库中update与delete使用表别名的深入研究

    本文介绍了UPDATE和DELETE SQL语句在Oracle, SQLite, PostgreSQL, MYSQL, mariadb等数据库系统中的执行差异,文中通过代码介绍的非常详细,对数据库开发和维护人员有指导意义,需要的朋友可以参考下
    2024-10-10
  • mysql查线上数据注意数据库的隔离级别

    mysql查线上数据注意数据库的隔离级别

    数据库的隔离级别关乎事务对其他并发事务的可见性及其对数据库的影响,隔离级别的选择决定了并发性能和数据一致性的平衡,SQL标准定义了四种隔离级别,每种级别都有不同的应用场景和防止并发问题的能力,感兴趣的可以了解一下
    2024-10-10
  • MySQL5.6免安装版环境配置图文教程

    MySQL5.6免安装版环境配置图文教程

    这篇文章主要为大家详细介绍了MySQL免安装版环境配置图文教程,很实用,感兴趣的小伙伴们可以参考一下
    2016-05-05
  • MySQL数据类型enum 枚举类型

    MySQL数据类型enum 枚举类型

    这篇文章主要介绍了MySQL数据类型enum 枚举类型,文章围绕主题展开详细的内容介绍,需要的小伙伴可以参考一下
    2022-06-06
  • mysql 5.7.21 解压版安装配置方法图文教程

    mysql 5.7.21 解压版安装配置方法图文教程

    这篇文章主要为大家详细介绍了mysql 5.7.21 解压版安装配置方法图文教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • MySQL实现去重的几种方法小结

    MySQL实现去重的几种方法小结

    在MySQL中,SELECT DISTINCT 和 GROUP BY 可以用来去除重复记录,二者有相似的功能,但在某些情况下有所不同,本文将通过代码示例给大家详细介绍这几种方法,感兴趣的小伙伴跟着小编一起来看看吧
    2024-07-07
  • 一次SQL如何查重及去重的实战记录

    一次SQL如何查重及去重的实战记录

    sql去重这可以说算是比较经典的面试题了,这篇文章主要给大家介绍了一次SQL如何查重及去重的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-03-03
  • MySQL中创建时间和更新时间的自动更新的实现示例

    MySQL中创建时间和更新时间的自动更新的实现示例

    本文主要介绍了MySQL中创建时间和更新时间的自动更新的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07

最新评论