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

两张表 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连接查询到底什么是驱动表

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

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

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

  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 left join 左连接查询关联n多张表

    left join 左连接即以左表为基准,显示坐标所有的行,右表与左表关联的数据会显示,不关联的则不显示.关键字为left join on. **基本用法如下: select table a left ...

  8. MySQL连接查询(多表查询)

    基本含义 连接就是指两个或两个以上的表(数据源) “连接起来成为一个数据源”. 连接语法的基本形式:from 表1 [连接方式] join 表2 [on 连接条件]; 连接的结果可以当做一个“表”来使 ...

  9. mysql把查询结果集插入到表理

    把表B的内容插入到表A INSERT INTO 1111_0 SELECT*FROM report_0 把查询结果集插入到表中 insert into A(a,b,c) select from B(a ...

随机推荐

  1. Error creating bean with name 'org.springframework.aop.aspectj.AspectJPointc

    问题 出现报错: Error creating bean with name 'org.springframework.aop.aspectj.AspectJPointc 原因 缺失两个库文件: as ...

  2. SpringBoot系列——状态机(附完整源码)

    1. 简单介绍状态机 2. 状态机的本质 3. 状态机应用场景 1. 简单介绍状态机 状态机由状态寄存器和组合逻辑电路构成,能够根据控制信号按照预先设定的状态进行状态转移,是协调相关信号动作.完成特定 ...

  3. 远程快速安装mysql

    远程服务器安装mysql数据库 https://www.cnblogs.com/renjidong/p/7047396.html 1.新开的云服务器,需要检测系统是否自带安装mysql # yum l ...

  4. tomcat依赖--linux

    https://tomcat.apache.org/download-90.cgi 下载 3,解压到usr/locat/tomcat 创建usr/local/tomcat Mkdir /usr/loc ...

  5. 第4章 最基础的分类算法-k近邻算法

    思想极度简单 应用数学知识少 效果好(缺点?) 可以解释机器学习算法使用过程中的很多细节问题 更完整的刻画机器学习应用的流程 distances = [] for x_train in X_train ...

  6. 【JAVA习题六】输入两个正整数m和n,求其最大公约数

    import java.util.Scanner; public class Oujilide欧几里得 { public static void main(String[] args) { // TO ...

  7. Docker部署nginx,tomcat,es,可视化

    nginx [root@iz2zeaet7s13lfkc8r3e2kz /]# docker pull nginx #下载 Using default tag: latest latest: Pull ...

  8. 初尝 Blazor WebAssembly

    一. 前言 Blazor 的整体介绍以及特点与优势,建议翻阅 Blazor 介绍. Blazor 是一个可是使用 .NET/C# 来编写交互式客户端的 Web UI 框架,在官网有一句话概括 &quo ...

  9. 学Linux驱动: 应该先了解驱动模型

    [导读] Linux设备林林总总,嵌入式开发一个绕不开的话题就是设备驱动开发,在做具体设备驱动开发之前,有必要对Linux设驱动模型有一个相对清晰的认识,将会帮助驱动开发,明白具体驱动接口操作符相应都 ...

  10. Spring-boot01

    本文记录Spring-Boot学习途中的点点滴滴. 其实Spring-Boot出来好长时间了,但是一直没去关注过.之前在我的印象里Spring-Boot好就好在减去了很多XML配置,加入了很多自动配置 ...