准备我们需要的表结构和数据

两张表 studnet(学生)表和score(成绩)表, 创建表的SQL语句如下

CREATE TABLE `student` (
`id` int(11) NOT NULL,
`no` varchar(20) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; CREATE TABLE `score` (
`id` int(11) NOT NULL,
`no` varchar(20) DEFAULT NULL,
`chinese` double(4,0) DEFAULT NULL,
`math` double(4,0) DEFAULT NULL,
`engilsh` double(4,0) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

MySQL连接查询分为以下三种

left join 左连接,用法如下,这种查询会把左表(student)所有数据查询出来,右表不存在的用空表示,结果图如下

select * from student s1 left join score  s2 on  s1.on = s2. on

right join 右连接, 用法如下,这种查询会把右表(score)所有数据查询出来,左表不存在的用空表示,结果图如下

select * from student s1 right join score s2 on s1.no = s2.no

inner join 内连接,用法如下,这种查询会把左右表都存在的数据查询出来,不存在数据忽略,结果图如下

select * from student s1 inner join score s2 on s1.no = s2.no

连接查询中需要注意的点

什么是驱动表,什么是被驱动表,这两个概念在查询中有时容易让人搞混,有下面几种情况,大家需要了解。

  1. 当连接查询没有where条件时,左连接查询时,前面的表是驱动表,后面的表是被驱动表,右连接查询时相反,内连接查询时,哪张表的数据较少,哪张表就是驱动表
  2. 当连接查询有where条件时,带where条件的表是驱动表,否则是被驱动表

怎么确定我们上面的两种情况呢,执行计划是不会骗人的,我们针对上面情况分别看看执行计划给出的答案

首先第一种情况,student表中3条数据,score表中2条数据,但两张表中只有一条数据是关联的(编号是1),看如下SQL查询

//左连接查询
explain select * from student s1 left join score s2 on s1.no = s2.no
//右连接查询
explain select * from student s1 right join score s2 on s1.no = s2.no
//内连接查询
explain select * from student s1 inner join score s2 on s1.no = s2.no

执行计划中靠前的表是驱动表,我们看下面三种图中,是不是全度符合情况一,第一张图中s1是驱动表,第二张图中s2是驱动表,第三种途中s2是驱动表





其次第二种情况,还是上面三种SQL语句,我们分别加上where条件,再来看看执行计划的结果是什么样呢?

//左连接查询
explain select * from student s1 left join score s2 on s1.no = s2.no
where s2. no = 1
//右连接查询
explain select * from student s1 right join score s2 on s1.no = s2.no
where s1.no = 1
//内连接查询
explain select * from student s1 inner join score s2 on s1.no = s2.no
where s1.no = 1

我们看下面三种执行计划结果,全都以where条件为准了,而且跟上面情况一的都相反了,因此情况二也是得到了验证.





连接查询优化

要理解连接查询优化,得先理解连接查询的算法,连接查询常用的一共有两种算法,我们简要说明一下

Simple Nested-Loop Join Algorithms (简单嵌套循环连接算法)

比如上面的查询中,我们确定了驱动表和被驱动表,那么查询过程如下,很简单,就是双重循环,从驱动表中循环获取每一行数据,再在被驱动表匹配满足条件的行。

for (row1 : 驱动表) {
for (row2 : 被驱动表){
if (conidtion == true){
send client
}
}
}
Index Nested-Loop Join Algorithms (索引嵌套循环连接算法)

上面双重for循环的查询中,相信很多研发人员看到这种情况第一个想法就是性能问题,是的,join查询的优化思路就是小表驱动大表,而且在大表上创建索引(也就是被动表创建索引),如果驱动表创建了索引,MySQL是不会使用的

for (row1 : 驱动表) {
索引在被驱动表中命中,不用再遍历被驱动表了
}
Block Nested-Loop Join Algorithm(基于块的连接嵌套循环算法)

其实很简单就是把一行变成了一批,块嵌套循环(BNL)嵌套算法使用对在外部循环中读取的行进行缓冲,以减少必须读取内部循环中的表的次数。例如,如果将10行读入缓冲区并将缓冲区传递到下一个内部循环,则可以将内部循环中读取的每一行与缓冲区中的所有10行进行比较。这将内部表必须读取的次数减少了一个数量级。

MySQL连接缓冲区大小通过这个参数控制 : join_buffer_size

MySQL连接缓冲区有一些特征,只有无法使用索引时才会使用连接缓冲区;联接中只有感兴趣的列存储在其联接缓冲区中,而不是整个行;为每个可以缓冲的连接分配一个缓冲区,因此可以使用多个连接缓冲区来处理给定查询;在执行连接之前分配连接缓冲区,并在查询完成后释放连接缓冲区

所以查询时最好不要把 * 作为查询的字段,而是需要什么字段查询什么字段,这样缓冲区能够缓冲足够多的行。

从上面的执行计划中其实我们已经看到了 useing join buffer了,是的,那是因为我们对两张表都有创建索引

三种算法优先级

第一种算法忽略,MySQL不会采用这种的,当我们对被驱动表创建了索引,那么MySQL一定使用的第二种算法,当我们没有创建索引或者对驱动表创建了索引,那么MySQL一定使用第三种算法

MySQL连接算法官方文档

https://dev.mysql.com/doc/refman/8.0/en/nested-loop-joins.html

掌握MySQL连接查询到底什么是驱动表的更多相关文章

  1. mysql连接查询:3个数据表操作研究

    首先,新建数据表aaa.bbb以及他们相关联的数据表avb:字段名如下图 填充点数据,如下: 上面设计表的时候,故意在两个表中有相同字段con,如果不做处理的话,在php程序中,看看什么情况?得到的结 ...

  2. MySQL连接查询驱动表被驱动表以及性能优化

    准备我们需要的表结构和数据 两张表 studnet(学生)表和score(成绩)表, 创建表的SQL语句如下 CREATE TABLE `student` ( `id` int(11) NOT NUL ...

  3. mysql连接查询经典小例题

    mysql连接查询: Mysql连接查询支持多表连接 对同一张表可以重复连接多次(别名在多次连接同一张表时很重要) 例题1: 下面有2张表 teams表 比赛结果表:result 问题: 得出一张表: ...

  4. mysql 连接查询 join

    本文用到的表 CREATE TABLE `cls` ( `cls_id` ) NOT NULL AUTO_INCREMENT, `name` ) NOT NULL, PRIMARY KEY (`cls ...

  5. MySQL连接查询、联合查询、子查询

    参考地址:http://blog.csdn.net/u011277123/article/details/54863371 1.MySQL连接查询 连接查询:将多张表(>=2)进行记录的连接(按 ...

  6. 细说MySQL连接查询:内连、左连和右连

    转: 细说MySQL连接查询:内连.左连和右连 简介: MySQL 的连接查询,通常都是将来自两个或多个表的行结合起来,基于这些表之间的共同字段,进行数据的拼接.首先,要确定一个主表作为结果集,然后将 ...

  7. 【博学谷学习记录】超强总结,用心分享|MySql连接查询超详细总结

    一.概述 在实际开发中,大部分情况下都不是在单表中进行数据操作,一般都是多张表进行联合查询.通常一个业务就会对应的有好几张表.MySql中的连接查询分为交叉连接,内连接,外连接三部分.其中交叉连接也叫 ...

  8. mysql连接查询,封装mysql函数

    连接查询 交叉连接语法: select  * | 字段列表 from 表1  cross join 表2 内连接: select *|字段列表 from 左表 inner join 右表 on 左表. ...

  9. Mysql 连接查询 Mysql支持的连接查询有哪些

    CREATE TABLE `chx` (   `id` VARCHAR(20) NOT NULL,   `name` VARCHAR(50) DEFAULT NULL,   `name2` CHAR( ...

随机推荐

  1. 【笔记3-24】Python语言基础

    环境搭建与语法入门 遇到问题解决问题 积累 英语单词 认真听讲,多敲代码 计算机是什么 计算机的组成 计算机的使用方式 TUI文本交互 GUI图形化交互 windows 的命令行 Shell.Term ...

  2. 大规模机器学习(Large Scale Machine Learning)

    本博客是针对Andrew Ng在Coursera上的machine learning课程的学习笔记. 目录 在大数据集上进行学习(Learning with Large Data Sets) 随机梯度 ...

  3. 医学图像 | 使用深度学习实现乳腺癌分类(附python演练)

    乳腺癌是全球第二常见的女性癌症.2012年,它占所有新癌症病例的12%,占所有女性癌症病例的25%. 当乳腺细胞生长失控时,乳腺癌就开始了.这些细胞通常形成一个肿瘤,通常可以在x光片上直接看到或感觉到 ...

  4. Redis数据结构——quicklist

    之前的文章我们曾总结到了Redis数据结构--链表和Redis数据结构--压缩列表这两种数据结构,他们是Redis List(列表)对象的底层实现方式.但是考虑到链表的附加空间相对太高,prev 和 ...

  5. Python基础 | pandas中dataframe的整合与形变(merge & reshape)

    目录 行的union pd.concat df.append 列的join pd.concat pd.merge df.join 行列转置 pivot stack & unstack melt ...

  6. 将Python执行代码打包成exe可执行文件

    安装pyinstaller pip3 install pyinstaller 进入py文件目录,执行以下指令 pyinstaller -F -w <文件名.py>,-F代表生成可执行文件, ...

  7. MySQL默认隔离级别为什么是RR

    曾多次听到“MySQL为什么选择RR为默认隔离级别”的问题,其实这是个历史遗留问题,当前以及解决,但是MySQL的各个版本沿用了原有习惯.历史版本中的问题是什么,本次就通过简单的测试来说明一下. 1. ...

  8. Python——Matplotlib库入门

    1.Matplotlib库简介 优秀的可视化第三方库 Matplotlib库由各种可视化类构成,内部结构复杂,受Matlab启发 matplotlib.pyplot是绘制各类可视化图形的命令子库,相当 ...

  9. 使用RandomString方法后,结果返回相同的随机数解决办法

    所遇问题: 在做超市管理系统的登录项目时,在对“随机数的产生”出现一个问题,在产生多个随机数的时候,出现了产生了多个一样的随机数,具体代码如下: /// <summary> /// 生成随 ...

  10. 20175314 《Java程序设计》第十一周学习总结

    20175314 <Java程序设计>第十一周学习总结 教材学习内容总结 URL类 URL类是java.net包中的一个类,用URL创建的对象可以获取URL中的资,其包括三部分信息:协议. ...