MySQL:如果用left join的话,左边的表一定是驱动表吗

一、前言

  在日常开发过程中关于MySQL的优化方面,我们知道小表驱动大表原理。例如left join,放在左边的表作为驱动表。但是用left join的话,左边的表一定是驱动表吗,本文将通过案例分析给出详细分析。

二、概念

  在MySQL中,JOIN操作涉及到两个或多个表的连接,其中一个表被称为驱动表(也称为外表),另一个表或多个表被称为被驱动表(也称为内表或从表)。

  驱动表(外表):在JOIN操作中,首先被访问的表称为驱动表。

  被驱动表(内表或从表):在JOIN操作中,与驱动表进行匹配的表称为被驱动表。

三、优化策略(小表驱动大表原理)

  在MySQL的JOIN操作中,当涉及到两个或多个表的连接时,其中一个表被选为驱动表(小表),另一个表作为被驱动表(大表)。小表驱动大表的原理就是尽量让数据量较小的表作为驱动表,通过其数据去匹配大数据量的表,以减少循环匹配的次数,从而提高查询性能。

示例:
  假设我们有两个表A和B,其中A表有1000行数据,B表有100万行数据。如果以A表作为驱动表去连接B表,那么最多只需要循环1000次;而如果以B表作为驱动表去连接A表,则需要循环100万次。显然,选择A表作为驱动表将大大提高查询性能。

选择小表作为驱动表的好处:

  减少循环次数:当驱动表的数据量较小时,循环的次数会相应减少,从而减少了整体的计算量。反之,如果大表作为驱动表,则需要多次循环遍历大表的数据去匹配小表,这将大大增加计算量。

  利用索引:如果小表上有合适的索引,MySQL可以更快地定位到需要的数据行,进一步减少扫描的行数。同时,索引的使用也可以提高JOIN操作的效率。

  优化器决策:MySQL的优化器会根据表的统计信息、索引情况、查询条件等因素来自动选择最佳的驱动表。优化器的目标是找到一种执行计划,使得查询的代价(如I/O操作、CPU时间等)最小。

四、案例分析

  我们在编写SQL的时候,通常情况下是这样子的
  LEFT JOIN:在左连接中,左边的表通常作为驱动表。
  RIGHT JOIN:在右连接中,右边的表作为驱动表。
  INNER JOIN:对于内连接,MySQL会自动选择数据量较小的表作为驱动表。

这是通常情况下,下面我们准备一些测试数据:

1. 准备数据:

a1表
在这里插入图片描述
a2表
在这里插入图片描述

2.准备查询语句1和查询语句2

语句1
select * from a1 left join a2 on(a1.f1=a2.f1) and (a1.f2=a2.f2); 语句2
select* from a1 left join a2 on(a1.f1=a2.f1)where (a1.f2=a2.f2);

3. 查询语句1的执行结果
在这里插入图片描述

4. 查询语句2的执行结果
在这里插入图片描述

5. 语句1的EXPLAIN执行结果分析
在这里插入图片描述
从EXPLAIN执行计划中看的出来

  驱动表是表a1,被驱动表是表a2。

  由于表a2的f1字段上没有索引,所以使用的是 Block Nested Loop Join(简称 BNL) 算法。

BNL算法基本原理

  将外层循环的结果集存入join buffer:在BNL算法中,外层循环(通常是较小的表或结果集)的行或结果集会被存储在一个称为join buffer的内存区域中。

  内层循环与buffer中的记录做比较:内层循环(通常是较大的表或结果集)的每一行数据会与整个buffer中的记录进行比较,而不是像传统的Nested Loop Join(NLJ)算法那样,每次只与外层循环的一行进行比较。

结合算法与执行计划语句1的执行过程如下:

  ①. 把表a1的内容读入join_buffer 中

  ②. 顺序扫描表a2,对于每一行数据,判断条件(a1.f1=a2.f1) and (a1.f2=a2.f2)是否满足,满足条件的记录, 作为结果集的一行返回。如果语句中有 where 子句,需要先判断 where 部分满足条件后,再返回。

  ③. 表a2扫描完成后,对于没有被匹配的表a1的行,把剩余字段补上 NULL,再放入结果集中。

6. 语句2的EXPLAIN执行结果分析
在这里插入图片描述
从EXPLAIN执行计划中看的出来

  以表a2为驱动表的。

语句2的执行过程
  顺序扫描表a2,每一行用a2.f1到表a1中去查,匹配到记录后判断a1.f2=a2.f2 是否满足,满足条件的话就作为结果集的一部分返回。

为什么呢,我们执行一下show warnings;看看优化器是怎么做的。
语句1
在这里插入图片描述

语句2
在这里插入图片描述

  在 MySQL 里,NULL 跟任何值执行等值判断和不等值判断的结果,都是 NULL。这里包括, select NULL = NULL 的结果,也是返回 NULL。

  因此,语句2里面 where a1.f2=a2.f2 就表示,查询结果里面不会包含 a2.f2是NULL的行,这样这个left join的语义就是“找到这两个表里面,f1、f2 对应相同的行。

  对于表a1中存在,而表a2中匹配不到的行,就放弃。这样,这条语句虽然用的是 left join,但是语义跟 join 是一致的。

  因此,优化器就把这条语句的 left join 改写成了 join,然后因为表 a1 的 f1 上有索引,就把表 a2 作为驱动表。

五、结论

1、即使我们在SQL语句中写成left join,执行过程还是有可能不是从左到右连接的。也就是说,使用left join时,左边的表不一定是驱动表。

2、如果需要left join的语义,就不能把被驱动表的字段放在where条件里面做等值判断或不等值判断,必须都写在on里面。

六、总结

通过对案例的分析,我们在写sql的时候,就有了优化方案:

1. 用小结果集驱动大结果集,减少外层循环的数据量

2. 如果小结果集和大结果集连接的列都是索引列,mysql在join时也会选择用小结果集驱动大结果集,因为索引查询的成本是比较固定的,这时候外层的循环越少,join的速度便越快。

3. 为匹配的条件增加索引:争取使用Index Nested-Loop Join,减少内层表的循环次数

4. 增大join buffer size的大小:当使用Block Nested-Loop Join时,一次缓存的数据越多,那么外层表循环的次数就越少,减少不必要的字段查询。

5. 当用到Block Nested-Loop Join时,字段越少,join buffer 所缓存的数据就越多,外层表的循环次数就越少。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/842415.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android开发 -- JNI开发

1.配置JNI环境 创建JNI文件夹 在项目的主目录中创建一个名为 JNI 的文件夹。这个文件夹将包含所有的本地源代码和配置文件。 编写Android.mk文件 这个文件是一个 Makefile,用来指导 NDK 如何编译和构建本地代码。 #清除之前定义的变量,确保每个模块的…

安装HAP时提示“code:9568344 error: install parse profile prop check error”错误

问题现象 在启动调试或运行应用/服务时,安装HAP出现错误,提示“error: install parse profile prop check error”错误信息。 解决措施 该问题可能是由于应用使用了应用特权,但应用的签名文件发生变化后未将新的签名指纹重新配置到设备的特…

[Java EE] 网络编程与通信原理(三):网络编程Socket套接字(TCP协议)

🌸个人主页:https://blog.csdn.net/2301_80050796?spm1000.2115.3001.5343 🏵️热门专栏:🍕 Collection与数据结构 (92平均质量分)https://blog.csdn.net/2301_80050796/category_12621348.html?spm1001.2014.3001.5482 🧀Java …

BookStack VS HelpLook两款知识库软件的区别

现在很多企业都会进行知识管理,在这个过程中,选择一个合适的知识库软件是一个不可避免的问题。在众多知识库软件中,HelpLook和BookStack这两款软件备受企业瞩目。不知如何选择,今天LookLook同学就简单介绍一下这两款知识库的区别&…

5.27作业

定义自己的命名空间my_sapce&#xff0c;在my_sapce中定义string类型的变量s1&#xff0c;再定义一个函数完成对字符串的逆置。 #include <iostream>using namespace std; namespace my_space {string s1;string reverse1(string s1);} using namespace my_space; int m…

深入解读 ChatGPT 的基本原理(个人总结版)

引言 背景 人工智能&#xff08;AI&#xff09;技术自20世纪中期诞生以来&#xff0c;经历了多次革新和进步。从最早的图灵测试&#xff0c;到20世纪末的深蓝计算机击败国际象棋冠军&#xff0c;再到21世纪初谷歌AlphaGo击败围棋冠军&#xff0c;AI技术的飞速发展改变了人们的…

BEVFormer论文详细解读

文章目录 1. 前言1.1 3D VS 4D1.2 .特征融合过程中可能遇到的问题1.3 .BEV提出背景1.4 .BEV最终得到了什么1.5 .输入数据格式 2. 背景/Motivation2.1 为什么视觉感知要用BEV&#xff1f;2.2 生成BEV视角的方法有哪些&#xff1f;为何选用Transformer呢&#xff1f; 3. Method/S…

Vapor Mode:Vue.js 的速度与激情,代码界的闪电侠

大家好&#xff0c;我是宝哥。 在快速发展的网络开发世界中&#xff0c;创新的Vue.js团队给我们带来了Vapor Mode。这个新模式优化了Vue的核心渲染过程&#xff0c;帮助我们的应用程序像轻烟一样运行&#xff0c;开发者无需深入复杂的优化工作。 在这篇文章中&#xff0c;我们将…

【微积分】Grant Sanderson

梯度&#xff1a;将各个偏导打包 定义&#xff1a;direction of steepest ascent 梯度向量的长度&#xff1a;最速上升方向的陡峭程度 方向导数&#xff1a;偏导的一种拓展 【托马斯微积分学习日记】13.1-线积分_哔哩哔哩_bilibili 概述 16.1line integrals of scalar funct…

直播预告:TinyVue 组件库实战解析,提升组件库构建技能!

在复杂的编码世界里&#xff0c;大家总希望能够寻找更高效、更简洁的解决方案来优化工作流程&#xff0c;提升开发效率。在5月28日晚7点 OpenTiny B站直播间&#xff0c;OpenTiny 非常荣幸地为大家带来一场关于 TinyVue 组件库实战分享的直播。届时&#xff0c;TinyVue 组件库成…

openEuler系统通过shell脚本安装openGauss 5.0.0企业版

上次提到的开机自启动的配置&#xff0c;获得了LD的称赞&#xff0c;然而LD的要求&#xff0c;都是“既得陇复望蜀”的&#xff0c;他又期望我们能实现openGauss安装的“自动化”&#xff0c;于是尝试了下用shell脚本部署&#xff0c;附件中的脚本实测有效&#xff0c;openEule…

图论(二)-图的建立

引言&#xff1a; 建图&#xff0c;将图放进内存的方法 常用的建图方式&#xff1a;邻接矩阵&#xff0c;邻接链表&#xff0c;链式前向星 一、邻接矩阵 通过一个二维数组即可将图建立&#xff0c;邻接矩阵&#xff0c;考虑节点集合 &#xff0c;用一个二维数组定义邻接矩…

迭代器模式(行为型)

目录 一、前言 二、迭代器模式 三、总结 一、前言 迭代器模式(Iterator Pattern&#xff09;是一种行为型设计模式&#xff0c;提供一种方法顺序访问一个聚合对象中各个元素&#xff0c;而又不暴露该对象的内部表示。总的来说就是分离了集合对象的遍历行为&#xff0c;抽象出…

gcc -m32 一堆报错:No such file or directory

问题&#xff1a;终端执行命令gcc -m32 *.c -o xxx.so 出现一堆缺失文件的报错。 解决办法&#xff1a;库没装全&#xff0c;终端执行下面的命令。 sudo apt install gcc-multilib

【设计模式】JAVA Design Patterns——Command(事务模式)

&#x1f50d;目的 将请求封装为对象&#xff0c;从而使你可以将具有不同请求的客户端参数化&#xff0c;队列或记录请求&#xff0c;并且支持可撤销操作。 &#x1f50d;解释 真实世界例子 有一个巫师在地精上施放咒语。咒语在地精上一一执行。第一个咒语使地精缩小&#xff0…

LabVIEW步开发进电机的串口控制程序

LabVIEW步开发进电机的串口控制程序 为了提高电机控制的精确度和自动化程度&#xff0c;开发一种基于LabVIEW的实时、自动化电机串口控制程序。利用LabVIEW软件的图形化编程特性&#xff0c;通过串口实时控制电机的运行参数&#xff0c;实现电机性能的精准控制与评估。 系统组…

nginx+nginx-http-flv-module在Linux服务器搭建

需求 在服务器搭建点播/视频平台的话需要在服务器搭建nginx和rtmp模块 rtmp模块 rtmp 模块有 nginx-rtmp-module &#xff0c;但是我们这里使用 nginx-http-flv-module 来替代。因为后者是基于前者开发的&#xff0c;前者拥有的功能后者都有&#xff0c;后者是国内的开发开…

基于PostGIS的mvt动态矢量切片的后台地图服务和前端调用

目录 一、背景 二、矢量切片 三、Mapbox的矢量切片格式 四、PostGIS生成矢量切片 ST_AsMVT: ST_AsMVTGeom: 五、导入试验数据 六、编写PostGIS函数 七:Java后端实现 八、Openlayers前端调用 一、背景 矢量切片技术目前已成为互联网地图的主流技术,无论是Mapbox还…

Vue.Draggable:强大的Vue拖放组件技术探索

一、引言 随着前端技术的不断发展&#xff0c;拖放&#xff08;Drag-and-Drop&#xff09;功能已经成为许多Web应用不可或缺的一部分。Vue.js作为现代前端框架的佼佼者&#xff0c;为开发者提供了丰富的生态系统和强大的工具链。Vue.Draggable作为基于Sortable.js的Vue拖放组件…

Slash后台管理系统源码阅读笔记 后面面板中的折线图统计卡片是怎么实现的?

之前的笔记发表在博客和公众号以后&#xff0c;得到了一部分同学的喜爱的认可&#xff0c;所以今天继续。 目前这个管理系统的代码已经处理了一小部分&#xff1a; 接下来&#xff0c;我们看看第二栏那三个折线图统计卡片是怎么实现的。 这三个卡片还是使用的 antd 一行三列…