MySQL关联查询如何优化

好久不见,关于这篇文章,我也是想了很久,还是决定写一篇文章,有很多同学问过 mysql 相关的问题,其实关联查询如何优化,首先我们要知道关联查询的原理是什么?

左连接 left join

SELECT 
	字段列表
FROM
	 A表 
LEFT JOIN 
	B表
ON 关联条件
WHERE 等其他子句

两表关联,以 left 左边的表为主表进行查询,除了返回满足连接条件的行以外,还返回左表中不满足条件的行。
如图所示:A 表是主表(驱动表),B 表是从表(被驱动表),颜色区域即所得结果集,结果集中返回匹配的行(交集),也返回 A 表中不匹配的行,不匹配字段用 NULL 表示。
在这里插入图片描述

右连接 right join

SELECT 
	字段列表
FROM
	 A表 
RIGHT JOIN 
	B表
ON 关联条件
WHERE 等其他子句

两表关联,以 right 右边的表为主表进行查询,除了返回满足连接条件的行以外,还返回右表中不满足条件的行。
如图所示:B 表是主表(驱动表),A 表是从表(被驱动表),颜色区域即所得结果集,结果集中返回匹配的行(交集),也返回 B 表中不匹配的行,不匹配字段用 NULL 表示。(同 left join,只不过主表位置不同)
在这里插入图片描述

内连接 inner join

SELECT 
	字段列表
FROM 
	A表 
INNER JOIN 
	B表
ON 关联条件
WHERE 等其他子句;

两表关联,返回符合 where 条件的结果集,即是 A 表 结果集,也是 B 表结果集,内联查询,没有左右主表之分,以哪张表为驱动表,取决于 MySQL service 层的优化器自己决定。
如图所示:
在这里插入图片描述

关联查询原理

前面讲解了连接查询的几种方式,现在谈谈 MySQL 底层是支持这几种连接查询的。
关联查询中涉及到多表的的查询,根据驱动类型分为驱动表和被驱动表,驱动表就是主表,被驱动表就是从表。
那么 MySQL 是如何进行join查询的呢?

1.Simple Nested-Loop Join (简单嵌套循环连接)

是从驱动表 A 中取出一条数据,遍历表 B,将匹配到的数据放到result,以此类推, 如下图所示:
在这里插入图片描述
比如驱动表A有10条,被驱动表B有100条,那么扫描次数是A+A*B, 每一次扫描其实就是从硬盘中读取数据加载到内存中,也就是一次IO,而IO是最大的瓶颈,所以效率低下,开销如下表:

开销统计简单嵌套循环连接
驱动表扫描次数1
被驱动表扫描次数A
读取记录数A+B*A
JOIN比较次数B*A
回表读取记录次数0

当然 MySQL 肯定不会这么粗暴的去进行表的连接,所以就出现了后面的两种对 Nested-Loop Join 优化算法。

2.Block Nested-Loop Join (块嵌套循环连接)

块嵌套循环连接是对上面一种算法的优化,简单嵌套是去驱动表中获取数据去匹配,和磁盘 IO 交互太多了,那么能否以一种批量的方式进行优化呢?mybatis 批量插入批量查询也是这个道理。而这种算法就是借鉴了这样的思想。
不再是逐条获取驱动表的数据,而是一块一块的获取,引入了 join buffer 缓冲区,将驱动表join相关的部分数据列、缓存到join buffer中,然后全表扫描被驱动表,被驱动表的每一条记录一次性和join buffer中的所有驱动表记录进行匹配(内存中操作),将简单嵌套循环中的多次比较合并成一次,降低了被驱动表的访问频率。整体如下图所示:
在这里插入图片描述
需要注意的是:从驱动表中缓存的列不仅仅是关联的的列,select 后面的列也会缓存起来。因此,为了能让 join buffer 缓存更多的数据,我们的 SQL 尽量不要 select *, 而是 select 用到的字段。
开销如下表:

开销统计块嵌套循环连接
驱动表扫描次数1
被驱动表扫描次数A*used_column_size/join_buffer_size+1
读取记录数A+B*(A*used_column_size/join_buffer_size)
JOIN比较次数B*A
回表读取记录次数0

join buffer的大小是可以设置的,默认情况下 join_buffer_size=256k。
join_buffer_size 的最大值在32位操作系统可以申请4G,而在64位操作系统下可以申请大于4G的 Join Buffer 空间(64位Windows除外,其大值会被截断为4GB并发出警告)。

3.Index Nested-Loop Join (索引嵌套循环连接)

索引嵌套循环连接(Index Nested-Loop Join)就是效率最高的,前提条件是被驱动表的关联字段建立了索引。通过驱动表匹配条件直接与被驱动表的索引进行匹配,避免和内存表的每条记录去进行比较,这样极大的减少了对内存表的匹配次数。如下图所示:
在这里插入图片描述
因为索引查询的成本基本一样,为了降低开销,驱动表是小表更加合适。所以我们常说把小表当作主表是有原因的。
开销如下表:

开销统计索引嵌套循环连接
驱动表扫描次数1
被驱动表扫描次数0
读取记录数A+B(match)
JOIN比较次数A*Index(Height)
回表读取记录次数B(match)(if possible)

如果被驱动表加索引,效率是非常高的,但如果索引不是主键索引,所以还得进行一次回表查询。相比,被驱动表的索引是主键索引,效率会更高。

块嵌套循环连接:对于被连接的数据子集较小的情况下,它是个较好的选择。
Hash Join: 是做大数据集连接时的常用方式,优化器使用两个表中较小(相对较小)的表利用 Join Key 在内存中建立散列值,然后扫描较大的表并探测散列值,找出与 Hash 表匹配的行。它能够很好的工作于没有索引的大表和并行查询的环境中,并提供最好的性能。Hash Join 只能应用于等值连接,这是由 Hash 的特点决定的。
在这里插入图片描述

总结:优化建议

前面讲了原理,从原理出发,讲一下优化的建议

  1. 被驱动表的连接字段建立索引,因为建立索引的查询方式是效率最高的。
  2. left join 或者 right join 这种外连接的情况,要保证小表(小结果集)作为驱动表,大表(大结果集)作为被驱动表,这样性能更好。
  3. 在查询字段的话,要避免写出 select * ,而是根据业务需要,需要查询出来的 select 出来就行,因为这些字段也会加入到 join buffer 中,减少额外的内存消耗。
  4. 能够直接多表关联的尽量直接关联,不用子查询,因为子查询的效率更加低。
  5. 在 sql 的查询计划的 extra 中,尽量避免出现 Using join buffer,有这个表示使用了块嵌套循环连接算法,尽量通过索引去解决。
  6. 尽量避免超过 3 张表以上的关联查询。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

软件测试面试,你准备好了吗?

最近有机会做一些面试工作,主要负责面试软件测试人员招聘的技术面试。 之前一直是应聘者的角色,经历了不少次的面试之后,多少也积累一点面试的经验,现在发生了角色转变。初次的面试就碰到个工作年限比我长的,也没有时…

北斗卫星在公路养护中的应用

北斗卫星在公路养护中的应用 北斗卫星是我国自主研发的一款卫星导航系统,它为公路养护工作提供了新的解决方案。通过使用北斗卫星技术,公路养护部门可以实时获取道路状况,提高工作效率,为交通安全保驾护航。 首先,北斗…

Java使用工厂方法实现聚合调用不同第三方接口进行实名验证

在Java中使用工厂方法实现聚合实名验证指的是创建一种实名验证服务,可以连接到不同的实名验证处理器,比如阿里、腾讯等。我们可以定义一个实名验证接口,然后实现不同的实名验证方式,最后使用一个工厂来创建相应的实名验证实例。以…

MySQL实现事务隔离的秘诀之锁

在MySQL中,有多种锁类型,我们先了解三种概念的锁,以便对接下来的内容有更好理解。 表级锁(Table Lock):对整个表加锁,其他事务无法修改或读取该表的数据,但可以对其他表进行操作。页…

SpringCloud入门(1) Eureka Ribbon Nacos

这里写目录标题 认识微服务SpringCloud 服务拆分和远程调用服务拆分案例实现远程调用 RestTemplate Eureka注册中心Eureka的结构和作用搭建eureka-server服务注册服务发现 Ribbon负载均衡 LoadBalancedLoadBalancerIntercepor源码解析负载均衡策略饥饿加载 Nacos注册中心安装与…

Java通过SSH连接数据库

一、实现思路 1 实现思路&#xff1a;本地–>跳板机–>目标数据库 2 IP走向&#xff1a;127.0.0.1:5432 --> 192.168.1.111 -->10.11.12.13:5432 二、引入maven <dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifa…

大规模电商平台数据采集难点分析♫

▁▃▅▇主要包括以下几方面&#xff1a; API工具 ◆◆数据量巨大 任何系统&#xff0c;在不同的数据量面前&#xff0c;需要的技术难度都是完全不同的。 如果单纯是将数据采到&#xff0c;可能还比较好完成&#xff0c;但采集之后还需要处理&#xff0c;因为必须考虑数据的规…

多模态数据融合简介#翻译

翻译自—— 感谢外国友人分享&#xff0c;鄙人在此翻译分享给大家INTRODUCTION TO DATA FUSION. multi-modality | by Haylat T | Haileleol Tibebu | Medium 多模态梳理_多模态图像和多模态方法的区别-CSDN博客 #这个网u也写得不错&#xff01; 多模态 神经网络是最著名的机…

申元智能邀您参观2024长三角快递物流供应链与技术装备展览会

2024年7月8-10日 | 杭州国际博览中心 展会介绍 2024长三角快递物流供应链与技术装备展览会&#xff08;杭州&#xff09;&#xff0c;于2024年7月8-10日在杭州国际博览中心召开&#xff0c;本届展会致力于全面展示快递物流上下游领域的创新解决方案&#xff0c;涵盖快递物流供…

接雨水-热题 100?-Lua 中文代码解题第4题

接雨水-热题 100&#xff1f;-Lua 中文代码解题第4题 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图&#xff0c;计算按此排列的柱子&#xff0c;下雨之后能接多少雨水。 示例 1&#xff1a; 输入&#xff1a;height [0,1,0,2,1,0,1,3,2,1,2,1] 输出&#xff1a;6 解释…

中型企业网络路由器配置(ensp)实验

vlan、vlan间路由、ospf协议等来实现三层交换机和单臂路由之间的通信 拓扑图&#xff1a; 1. 配置三层交换机vlan和vlan间路由 SW1 #进入视图 sys sysn sw1 undo info-center enable#配置vlan vlan batch 10 20 30 40 50 60#配置access口 int g0/0/1 port link-type access …

第十二届蓝桥杯省赛CC++ 研究生组

十二届省赛题 第十二届蓝桥杯省赛C&C 研究生组-卡片 第十二届蓝桥杯省赛C&C 研究生组-直线 第十二届蓝桥杯省赛C&C 研究生组-货物摆放 第十二届蓝桥杯省赛C&C 研究生组-路径 第十二届蓝桥杯省赛C&C 研究生组-时间显示 第十二届蓝桥杯省赛C&C 研究生组…

数字资产管理系统、企业数字资产管理软件

数字资产管理系统&#xff08;DAMS&#xff09;是一系列软件&#xff0c;它提供了一个开放平台&#xff0c;支持对多媒体数据的采集、创建、管理、存储、归档、检索、传输和显示。这些多媒体数据包括图像、视频、声音、文本和电影剪辑等。这些基础软件不仅是内容创作&#xff0…

普洛斯怀来数据中心获Uptime MO认证,以高品质服务持续提升客户体验

近日&#xff0c;普洛斯怀来数据中心顺利通过Uptime M&O&#xff08;运维与管理&#xff09;认证&#xff0c;获得Uptime Institute颁发的认证证书。普洛斯数据中心致力于为客户提供高品质、高可靠的运维服务&#xff0c;此项认证&#xff0c;标志着普洛斯数据中心运营及管…

基于springboot的班级综合测评管理系统的设计与实现

目录 背景 技术简介 系统简介 界面预览 背景 随着电子技术的广泛渗透和迅猛发展&#xff0c;网络化的管理平台得到了大规模的应用。众多的公共机构和商业组织都在积极推进管理流程的电子化转型&#xff0c;班级的综合评价管理系统亦是如此&#xff0c;从传统的手工操作转变…

移动硬盘故障解析:解决无法访问且位置不可用问题

在我们日常的工作和生活中&#xff0c;移动硬盘已成为存储和传输数据的重要工具。然而&#xff0c;有时我们会遇到移动硬盘无法访问且位置不可用的情况&#xff0c;这无疑给数据的存储和访问带来了极大的困扰。本文将深入探讨这一问题&#xff0c;分析其原因&#xff0c;并给出…

C#事件实例详解

一、什么是事件&#xff1f; 在C#中,事件(event)是一种特殊的类成员,它允许类或对象通知其他类或对象发生了某些事情。 从语法上看,事件的声明类似于字段,但它们在功能和行为上有一些重要的区别。 从技术角度来说,事件实际上是一个封装了事件订阅和取消订阅功能的委托字段。…

JS08-DOM节点完整版

DOM节点 查找节点 父节点 <div class="father"><div class="son">儿子</div></div><script>let son = document.querySelector(.son)console.log(son.parentNode);son.parentNode.style.display = none</script>通过…

基于Java的厦门旅游电子商务预订系统(Vue.js+SpringBoot)

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 景点类型模块2.2 景点档案模块2.3 酒店管理模块2.4 美食管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 学生表3.2.2 学生表3.2.3 学生表3.2.4 学生表 四、系统展示五、核心代码5.1 新增景点类型5.2 查询推荐的…

【GIT】最好用的git可视化教程网站推荐

最好用可视化学习git 网站:https://learngitbranching.js.org/?demo&localezh_CN 玩遍所有关卡&#xff0c;花半天时间便能掌握git &#x1f603; 本地仓库 基础命令介绍 git commit 提交 git branch <分支名> 创建分支 git checkout <分支名> 切换分支 git…