驱动表与被驱动表的含义

在MySQL中进行多表联合查询时,MySQL会通过驱动表的结果集作为基础数据,在被驱动表中匹配对应的数据,匹配成功合并后的临时表再作为驱动表或被驱动表继续与第三张表进行匹配合并,直到所有表都已匹配完毕,最后将结果返回出来。匹配算法:Nested-Loop Join(嵌套循环连接),在MySQL中有三种具体的实现算法:

  • Simple Nested-Loop Join:简单嵌套循环连接
  • Index Nested-Loop Join:索引嵌套循环链接
  • Block Nested-Loop Join:缓存快嵌套循环链接

Simple Nested-Loop Join

简单嵌套循环连接实际上就是简单粗暴的嵌套循环,如果驱动表有100条数据,被驱动表有100条数据,那么在匹配时会将驱动表的每一条数据作为匹配条件去被驱动表中逐个比较,实际上就要比较100*100=10000次,可以想象这种比较效率是非常低下的。

Index Nested-Loop Join

索引嵌套循环连接是基于被驱动表的索引进行连接的算法,通过驱动表的匹配条件与被驱动表的索引进行匹配,避免和每条记录比较,从而利用索引的查询减少匹配次数,提高查询的性能。但要注意的是被驱动表的关联条件必须要有索引时才能用到Index Nested-Loop Join。另外由于用到索引,如果是非聚簇索引并且查询的数据包含了被驱动表的其他字段,则会回到被驱动表再查询一次对应的数据,即回表,多了IO操作。

Block Nested-Loop Join

缓存嵌套循环连接通过一次性缓存多条驱动表数据、参与查询的列到Join Buffer里,然后拿Join Buffer里的数据批量与被驱动表中的数据进行比较,从而减少了循环匹配次数。

关于Join Buffer

  1. Join Buffer会缓存所有参与查询的列,而不是只有Join的匹配列
  2. 可以调整MySQL的join_buffer_size缓存大小,join_buffer_size的默认值是256K,最大值在MySQL 5.1.22版本前是4G,而之后的版本才能在64位操作系统下申请大于4G的空间
  3. 要使用Block Nested-Loop Join算法需要开启优化器管理配置的optimizer_switch的设置block_nested_loop为on,默认为on

当查询优化器不使用Index Nested-Loop Join算法的时候,默认使用Block Nested-Loop Join算法。

联合查询的性能优化原则

明白联合查询的原理是驱动表与被驱动表通过条件嵌套循环连接匹配后,查询性能优化的思路就是:减少循环比较次数。可以通过以下几个原则来进行优化。

1. 以数据量小的表作为驱动表,数据量大的表作为被驱动表。

通过上面的分析可以得知,MySQL在联合查询中是用驱动表的数据作为筛选条件在被驱动表中进行匹配,所以假设table1作为驱动表,数据有10000条,table2作为被驱动表的数据有100条,并且被table2中有索引,那么用Index Nested-Loop Join算法进行匹配时要进行10000次的关联操作。但如果反过来用table2作为驱动表,table1作为被驱动表,只需要进行100次关联即可完成匹配,效率也会大大提高,其他的连接算法也类似。简单说通常情况下要用小表驱动大表。

但是这里的小表和大表是根据查询条件相对而言的,大小的计算是要根据查询条件和具体的字段进行衡量,假如查询条件指定了table1的搜索范围,即table1满足查询条件的行数有90行,那么计算公式为:90乘以参与关联查询字段的大小总和,若结果小于table2满足查询条件后的行数乘以参与关联查询字段的大小,则table1为小表,否则table1为大表。

2. 为匹配的条件增加索引

匹配的条件字段列尽量使用有索引的,争取使用Index Nested-Loop Join算法进行关联,减少被驱动表的循环次数

3. 增大join_buffer_size的大小

当使用Block Nested-Loop Join算法时,增大join_buffer_size的大小可以使驱动表一次缓存更多的数据,从而减少总体循环匹配的次数

4. 减少不必要的字段查询

  • 当用到Block Nested-Loop Join算法时,字段越少,join Buffer所缓存的数据就越多,那么循环的次数就越少。
  • 当用到Index Nested-Loop Join算法时,如果可以不回表查询,即只查询索引列,利用覆盖索引则可能提升匹配效率

如何确定驱动表与被驱动表

  • 在使用join连接并且无where条件时:

    1. left join左边的表为驱动表,右边的为被驱动表
    2. right join右边的表为驱动表,左边的为被驱动表
    3. 使用join时,MySQL会自动判断左右两边哪边是小表,哪边是大表。小表作为驱动表,大表作为被驱动表,小表与大表的判断原则为上面讲到的根据行数和参与关联的字段计算得出。
  • 在使用in\exists时
    1. 使用in时,驱动表和被驱动表由MySQL的执行器根据表的大小自动选择
    2. 使用exists时,外部表为驱动表,内部表为被驱动表。无论加什么查询条件都无法改变

使用join连接查询时如果有where条件,则MySQL执行器会根据查询条件过滤后的结果自动选择驱动表或被驱动表。

MySQL的驱动表与被驱动表的更多相关文章

  1. mysql驱动表与被驱动表及join优化

    驱动表与被驱动表 先了解在join连接时哪个表是驱动表,哪个表是被驱动表:1.当使用left join时,左表是驱动表,右表是被驱动表2.当使用right join时,右表时驱动表,左表是驱动表3.当 ...

  2. 掌握MySQL连接查询到底什么是驱动表

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

  3. 3.mysql小表驱动大表的4种表连接算法

    小表驱动大表 1.概念 驱动表的概念是指多表关联查询时,第一个被处理的表,使用此表的记录去关联其他表.驱动表的确定很关键,会直接影响多表连接的关联顺序,也决定了后续关联时的查询性能. 2.原则 驱动表 ...

  4. SQL Server中多表连接时驱动顺序对性能的影响

    本文出处:http://www.cnblogs.com/wy123/p/7106861.html (保留出处并非什么原创作品权利,本人拙作还远远达不到,仅仅是为了链接到原文,因为后续对可能存在的一些错 ...

  5. 重新学习Mysql数据13:Mysql主从复制,读写分离,分表分库策略与实践

    一.MySQL扩展具体的实现方式 随着业务规模的不断扩大,需要选择合适的方案去应对数据规模的增长,以应对逐渐增长的访问压力和数据量. 关于数据库的扩展主要包括:业务拆分.主从复制.读写分离.数据库分库 ...

  6. Mysql InnoDB 共享表空间和独立表空间

    前言:学习mysql的时候总是习惯性的和oracle数据库进行比较.在学习mysql InnoDB的存储结构的时候也免不了跟oracle进行比较.Oracle的数据存储有表空间.段.区.块.数据文件: ...

  7. MySQL学习笔记三:库和表的管理

    1.MySQL数据库服务配置好后,系统会有4个默认的数据库. information_schema:虚拟对象,其对象都保存在内存中 performance_schema:服务器性能指标库 mysql: ...

  8. mysql在线修改表结构大数据表的风险与解决办法归纳

    整理这篇文章的缘由: 互联网应用会频繁加功能,修改需求.那么表结构也会经常修改,加字段,加索引.在线直接在生产环境的表中修改表结构,对用户使用网站是有影响. 以前我一直为这个问题头痛.当然那个时候不需 ...

  9. 在mysql数据库中制作千万级测试表

    在mysql数据库中制作千万级测试表 前言: 最近准备深入的学一下mysql,包括各种引擎的特性.性能优化.分表分库等.为了方便测试性能.分表等工作,就需要先建立一张比较大的数据表.我这里准备先建一张 ...

  10. MySQL表的创建和表中数据操作

    这篇文章主要介绍在navicat的命令界面操作mysql.主要涉及建立表结构,和对表中数据的增加删除修改查询等动作.站在一个新手角度的简单mysql表结构和数据操作. ☆ 准备工作 1,保证自己的电脑 ...

随机推荐

  1. 将onnx的静态batch改为动态batch及修改输入输出层的名称

    目录 背景 操作 修改输入输出层 修改输入输出层名称 完整代码 背景 在模型的部署中,为了高效利用硬件算力,常常会需要将多个输入组成一个batch同时输入网络进行推理,这个batch的大小根据系统的负 ...

  2. 检测到 #include 错误。请更新 includePath。已为此翻译单元 禁用波形曲线

    也有可能是VSCode抽风了 重启就好

  3. 【Java 新的选择】,Solon v2.3.8 发布

    Solon 是什么开源项目? 一个,Java 新的生态型应用开发框架.它从零开始构建,有自己的标准规范与开放生态(历时五年,已有全球第二级别的生态规模).与其他框架相比,它解决了两个重要的痛点:启动慢 ...

  4. 自用 .net C# List集合和DataTable互转,可自定义表头

    using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.R ...

  5. 文件上传的multipart/form-data属性,你理解了吗

    form表单经常用于前端发送请求,比如:用户填写信息.选择数据.上传文件,对于不同的场景,上传数据的格式也会有些区别. action action 表示该请求的 url 地址,定义在form上,请求的 ...

  6. 一文了解react中定义样式(css/less/sass)的常用方法

    react中通过jsx的语法方式,将html标签和js语法联系在一起,而css的编写方式,没有明确的指定编写方式,目前就有很多不同方法,每个方式各有其优缺点,我们一起来看看常用的定义方式有哪些. 最基 ...

  7. [nginx]定制http头信息

    前言 修改http响应头信息,相关Nginx模块:ngx_http_headers_module expires 语法: expires [modified] time; expires [modif ...

  8. docker 安装 Redis环境

    一.Docker搜索redis镜像 命令:docker search <镜像名称> docker search redis 二.Docker拉取镜像 命令::docker pull < ...

  9. 文心一言 VS 讯飞星火 VS chatgpt (81)-- 算法导论7.4 6题

    六.如果用go语言,考虑对 PARTITION 过程做这样的修改:从数组 A 中随机选出三个元素,并用这三个元素的中位数(即这三个元素按大小排在中间的值)对数组进行划分.求以a 的函数形式表示的.最坏 ...

  10. 分布式测试插件 pytest-xdist 使用详解

    使用背景: 大型测试套件:当你的测试套件非常庞大,包含了大量的测试用例时,pytest-xdist可以通过并行执行来加速整体的测试过程.它利用多个进程或计算机的计算资源,可以显著减少测试执行的时间. ...