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

两张表 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 report formats of SFDC

    Choose one of the following report formats using the Format menu of the report builder. Tabular form ...

  2. 从零开始的JSON库

    从零开始的JSON库 项目地址 jsoncpp ,此项目受到 leptjson 启发,实现了最基本的功能,仅作学习使用. 提供简单的 parse() 和 generate() 方法将 JSON 文本解 ...

  3. 使用FME对CAD管网数据进行过滤、聚合、中心点替换

    1.首先加载CAD数据,并暴露出需要使用到的相关字段.比如:block_number.fme_geometry.fme_color等字段. 2.对一个元素有多种类型部件的需要进行过滤,例如本次的检修井 ...

  4. 常见Web安全漏洞--------CSRF

    1,CSRF (Cross Site Request Forgery, 跨站域请求伪造),也可以说是模拟请求. 2,黑客获取到了token 令牌,发送恶意模拟请求,攻击网站,防御方法可以参考api 接 ...

  5. 事务框架之声明事务(自动开启,自动提交,自动回滚)Spring AOP 封装

    利用Spring AOP 封装事务类,自己的在方法前begin 事务,完成后提交事务,有异常回滚事务 比起之前的编程式事务,AOP将事务的开启与提交写在了环绕通知里面,回滚写在异常通知里面,找到指定的 ...

  6. Spring - 事务管理概述

      什么是事务管理? 第一个问题:什么是事务? 事务一般是相对数据库而言的,对于数据库一次操作就属于一个事务, 一次操作可以是几句 SQL 语句,也可以是若干行 JDBC 的 Java 语句.事务既然 ...

  7. [poj1797]Heavy Transportation<最大生成树prim&kruskal>

    题目链接:http://poj.org/problem?id=1797 题意:给定n个点,m条边,每条边连接两点切有权值.求点1到点n的路径的上的最小边的值最大... 翻别人博客找到的题,方法挺多的, ...

  8. 【WPF学习】第六十五章 创建无外观控件

    用户控件的目标是提供增补控件模板的设计表面,提供一种定义控件的快速方法,代价是失去了将来的灵活性.如果喜欢用户控件的功能,但需要修改使其可视化外观,使用这种方法就有问题了.例如,设想希望使用相同的颜色 ...

  9. python:简单爬取自己的一篇博客文章

    1.爬取文章地址:https://www.cnblogs.com/Mr-choa/p/12495157.html 爬取文章的标题.具体内容,保存到文章名.txt 代码如下: # 导入requests模 ...

  10. SHTC3温湿度传感器的使用

    1.SHTC3简单说明 SHTC3是一个检测温度.湿度的传感器,可以检测-40℃~125℃的温度范围和0%~100%的湿度范围. SHTC3的工作电压范围为:1.62V~3.6V. SHTC3使用的通 ...