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

两张表 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. ArrayList的传值问题

    ArrayList是一个对象类型,记录一下遇到的传值问题 假设两个ArrayList类型的值a和b,a有值,b无值,想把a的值全部复制给b. 如果使用 b = a; 进行赋值,会将a的地址赋值给b,当 ...

  2. SpringCloud服务的注册发现--------zookeeper实现服务与发现 + Ribbon实现客户端负载均衡

    1,Eureka 闭源了,但是我们可以通过zookeeper实现注册中心的功能. zookeeper 是一个分布式协调工具,可以实现服务的注册和发现,配置中心,注册中心,消息中间件的功能 2,工具准备 ...

  3. MySql查询当天、本周、本月、本季度、本年的数据

    1.今天 SELECT * FROM 表名 WHERE TO_DAYS(时间字段名) = TO_DAYS(NOW()); 2.昨天 ; 3.本周 SELECT * FROM 表名 WHERE YEAR ...

  4. gold 30 mins

  5. [noip模拟]食物中毒<暴搜+状压优化>

    问题描述 Bqc经过一段时间的研究发现,要解这种毒需要一种特殊的药物.不幸的是,这种药物在 市面上不存在,没有办法Bqc只好亲自制得这种药物.它含有M种化学物质A1,A2,…,AM.现 在Bqc的手上 ...

  6. 使用 Visual Studio 开发、测试和部署 Azure Functions(二)测试,部署

    1,引言 上一篇介绍了使用使用 Visual Studio 开发 "Azure Functions" 函数,此篇介绍 “Azure Functions” 的测试以及直接从 Vist ...

  7. C - 啥~ 渣渣也想找玩数字 HDU - 2141(有序序列枚举 + 二分优化查找)

    题目描述 可爱的演演又来了,这次他想问渣渣一题... 如果给你三个数列 A[],B[],C[],请问对于给定的数字 X,能否从这三个数列中各选一个,使得A[i]+B[j]+C[k]=X? 输入 多组数 ...

  8. H - 覆盖的面积(线段树-线段扫描 + 离散化(板题))

    给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input 输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1 ...

  9. CSAPP实验——DataLab

    任务:按照要求补充13个函数,会限制你能使用的操作及数量 bitXor(x,y) 只使用 ~ 和 & 实现 ^ tmin() 返回最小补码 isTmax(x) 判断是否是补码最大值 allOd ...

  10. 【Net】ABP框架学习之它并不那么好用

    前言 上一篇文章介绍了ABP的Web API,本文在继续介绍ABP的其他内容. 在ABP中,WEBAPI是一个值得用的东西.但其他东西,就不一定是那么好用了. 下面我们看一下ABP的Controlle ...