SQL 优化(四):合理使用 join

news2024/12/23 1:14:52

在工作的时候经常听到的一句话就是,“这条 SQL 因为 join 了很多表,导致查询速度比较慢”,可以从侧面反映出,join语句对性能的影响是比较大的,而且大部分人不知道如何进行优化。这篇文章我们来讲讲join的执行过程,以及该如何对join语句进行优化

AB两张表,表的初始化语句如下

CREATE TABLE `A` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `a`(`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE B like A;

接着我们向表A插入 100 条数据,向表B插入 1000 条数据

Index Nested-Loop Join

我们看下这条语句

select * from A straight_join B on A.a = B.a

explain 查看该语句的执行计划

可以看到,该语句对 A 表做了全表扫描,并使用了 B 表上的索引,完整的执行流程如下:

  1. 从 A 表中读取一行数据 R
  2. 从 R 中取出 a 字段,根据 a 字段到 B 表中查询 (使用B表的索引a
  3. 从 B 表中取出 B 表的数据行
  4. 重复 1~3,直到 A 表遍历结束

可以看到,整个查询流程扫描了 200 行,其中对 A 表做全表扫描了 100 行,另外 100 行是对 B 表的嵌套查询中产生的

对于这种遍历驱动表A,然后根据A中每一行的值,去被驱动表B查找,并使用驱动表B的索引的搜索过程,由于在形式上与我们写代码时的嵌套查询类似,因此该过程称之为 Index Nested-Loop Join (简称NLJ)

Simple Nested-Loop join

如果我们将查询语句写成这样

select * from A straight_join B on A.a = B.b

由于 B 表的 b 字段上没有索引,因此 sql 的执行流程如下

  1. 从 A 表中读取一行数据 R
  2. 从 R 中取出 a 字段,根据 a 字段到 B 表中查询 (对 B 表进行全表遍历)
  3. 从 B 表中取出 B 表的数据行
  4. 重复 1~3,直到 A 表遍历结束

NLJ不同的是,由于进行A.a=B.b的时候,无法使用索引,所以整个查询总共扫描了 1000 * 100 = 10w 行,这种查询方式也被称为 Simple Nested-Loop Join

Block Nested-Loop Join

由于Simple Nested-Loop Join对两张表都做了全表扫描,比较笨重,在性能上表现很差。为了解决这个问题,MySQL 使用了另外一种叫做Block Nested-Loop Join的算法(简称 BNL)

查看select * from A straight_join B on A.a = B.b;的执行计划,可以看到,MySQL 并没有使用Simple Neststed-Loop Join,而是使用Block Nested Loop Join

BNL的执行流程如下:

  1. 把 A 表的数据读出来放到join_buffer中,由于我们是select *,所以相当于把整个 A 表放入到内存中
  2. 遍历 B 表,取出 B 表的每行数据,将其与内存中的 A 表进行比对,满足 join 条件的,作为结果集的一部分返回

这时你可能会说,如果 A 表的数据太多,内存放不下怎么办呢?这也很简单,只需要对 A 表进行分段缓存就行啦,这时候的执行流程如下:

  1. 扫描 A 表,顺序将 A 表的数据加入到join_buffer中,直到join_buffer满了,执行第二步
  2. 扫描 B 表,取出 B 表的每行数据,将其与join_buffer中的数据进行比对,满足 join 条件的,作为结果集的一部分返回
  3. 清空join_buffer,继续读取 A 表的数据,重复 1、2 步,直到遍历结束

对 A 表进行分段(分块)缓存,这也是Block Nested-Loop Join名字的由来。可以看到,Block Nested-Loop JoinSimple Nested-Loop Join的唯一区别,就是 NBL 对驱动表进行了缓存,将嵌套匹配的操作都放到内存中进行,大大提升了关联查询的性能

10w 次内存操作跟 10w 次磁盘操作,性能相差还是很大的

如何优化 join

了解 join 的三种查询算法后,可以知道,NLJ 的查询性能是最快的。所以第一个优化方案是:尽量使用索引字段进行关联,让 MySQL 能使用 NLJ

还有一点是,不管哪种查询算法,都对驱动表做了全表扫描,所以我们在关联的时候,应该用“小表”作为驱动表,“大表”作为被驱动表,这样就能减少全表扫描的行数了,提高性能

注意,“小表”、“大表” 指的不一定是表的数据量大小,而是在查询的时候,扫描行数多的称之为“大表”,反之称之为“小表”

如 t1 表有 10w 数据,t2 表有 1000 数据,那么可以用 t2 表做驱动表,sql 可以这样写

select * from t2 straight_join t1 on t2.a = t1.a;

如果 SQL 带 where 条件,where 后的 t1 表只有 100 条数据,这时候,t1 就是“小表”,t2 则是“大表”,那么就应该用 t1 做驱动表

select * from t1 
straight_join t2 on t1.a = t2.a
where t1.id <= 100;

关注公众号:huangxy,一起学习,一起进步

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

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

相关文章

PC C++ SDK 全局函数、防录制功能、下载器、播放器

本文档提供了使用 CSDK 的操作步骤及代码示例&#xff0c;通过本文您可以快速了解如何使用 SDK 提供的功能。您也可以通过 Demo 中的示例进行了解和自有业务开发。 SDK 名词含义及功能说明 参见 plv-player-def.h SDK 全局函数 设置日志&#xff0c;日志过滤项。设置观众信息…

ENVI遥感影像处理—水体提取

2 .水体提取 &#xff08;1&#xff09;导入经过大气校正后的影像FLAASH_result.dat。 &#xff08;2&#xff09;选择工具箱中ToolBox——Band Ratio——Band Math&#xff0c;输入(float(b1)-float(b2))/(float(b1)float(b2))&#xff0c;点击Add to List&#xff0c;选中公…

R3LIVE环境搭建

一、安装ros、livox sdk、livox_ros_driver 安装方法[参考] 二、CGAL和pcl_viewer sudo apt-get install libcgal-dev pcl-tools 三、opencv&#xff08;≥3.3&#xff09; 3.1 命令检查 OpenCV 版本&#xff0c;如果 openCV 版本低于 OpenCV-3.3, 更新openCV版本为3.3.1、3…

Kubernetes 多集群管理工具 - Kuboard

Kuboard 是Kubernetes 多集群管理工具&#xff0c;是一个界面化的web网站&#xff0c;使用起来非常方便。在Kuboard中可以导入集群&#xff0c;在kuboard上可以完成很多的运维工作&#xff0c;比如创建命名空间、创建标签、运行服务、修改pod数量等等。 一&#xff1a;kuboard…

【JavaEE初阶】CSS

摄影分享~ 文章目录 一.CSS基本规范1. CSS基本语法规范2.CSS选择器 二.CSS常用属性1. 字体属性2.文本属性3.背景属性4.圆角矩形5.元素的显示模式块级元素行内元素 6.盒子模型边框内边距外边距 7.弹性布局 一.CSS基本规范 层叠样式表。(Cascading Style Sheets) CSS 能够对网页…

【零基础入门学习Python---Python中Web开发基础之快速入门实践】

&#x1f680; 零基础入门学习Python&#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜…

springboot医院自助服务系统-计算机毕设 附源码74853

springboot医院自助服务系统 目 录 摘要 1 绪论 1.1研究意义 1.2研究背景 1.3springboot框架介绍 1.3论文结构与章节安排 2 医院自助服务系统系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能分析 2.3.1 功能性分析 2.3.2 …

五、Eureka服务注册、续约、剔除、下线源码分析

Eureka 概念的理解 1 服务的注册 当项目启动时&#xff08;eureka 的客户端&#xff09;&#xff0c;就会向 eureka-server 发送自己的元数据&#xff08;原始数据&#xff09;&#xff08;运行的 ip&#xff0c;端口 port&#xff0c;健康的状态监控等&#xff0c;因为使用的…

ICLR 2023 | Self-Consistency: Google超简单方法改善大模型推理能力

大家好&#xff0c;我是HxShine。 今天分享一篇Google Research, Brain Team的一篇文章&#xff0c;SELF-CONSISTENCY IMPROVES CHAIN OF THOUGHT REASONING IN LANGUAGE MODELS[1]&#xff1a;利用自洽性提高语言模型中的思维链推理效果 这篇文章方法非常简单但是效果非常好…

vite配置指定浏览器打开-2023年7月3日

vue3vitevscode-2023年7月3日 官方demo环境下 官方demo环境下 找到vite.config.js增加如下代码 server:{open: {"process.env.BROWSER":C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe}}

docker安装RocketMQ(附填坑经验connect to <172.17.0.3:10909> failed)

目录 一、docker部署RocketMQ1、简易说明2、docker拉取RocketMQ镜像\RocketMQ控制台3、获取RocketMQ配置文件4、RocketMQ配置文件描述5、docker启动RocketMQ6、进入RocketMQ控制台 二、填坑经验错误一: connect to <172.17.0.3:10909> failed错误二: maybe your broker m…

C++静态库与动态库

什么是库 库是写好的现有的&#xff0c;成熟的&#xff0c;可以复用的代码。现实中每个程序都要依赖很多基础的底层库&#xff0c;不可能每个人的代码都从零开始&#xff0c;因此库的存在意义非同寻常。 本质上来说库是一种可执行代码的二进制形式&#xff0c;可以被操作系统…

英伟达新SOTA可对未知物体进行6D追踪和3D重建

物体可以在整个视频中自由移动&#xff0c;甚至经历严重的遮挡。英伟达的方法在目标上与物体级 SLAM 的先前工作类似&#xff0c;但放松了许多常见的假设&#xff0c;从而能够处理遮挡、反射、缺乏视觉纹理和几何线索以及突然的物体运动。 英伟达方法的关键在于在线姿态图优化…

J2EE自定义mvc【框架配置及功能】

目录 一、配置步骤 二、配置框架前三步 导入相应的jar 导入相应的Class 导入xml文件 三、优化基本操作&#xff08;增删改&#xff09; 1、基础优化 编写实体类 编写BookDao类 优化BookDao JUnit测试 2、后台优化 3、前端优化 一、配置步骤 将框架打成jar包&…

SQL Server SQL语句

在很多情况下&#xff0c;可以用CREATE TABLE语句创建数据表、使用ALTER TABLE语句修改表结构、使用DROP TABLE语句删除表&#xff1b; 可以使用CREATE DATABASE创建数据库、ALTER DATABASE修改文件或文件组、DROP DATABASE语句删除数据库&#xff1b; 1、数据定义语句&#x…

web安全php基础_php变量命名及其作用域

php变量命名规则 php变量命名规则 变量以 $ 符号开始&#xff0c;后面跟着变量的名称变量名必须以字母或者下划线字符开始变量名只能包含字母数字字符以及下划线&#xff08;A-z、0-9 和 _ &#xff09;变量名不能包含空格变量名是区分大小写的&#xff08;$y 和 $Y 是两个不…

戴尔笔记本开机输入密码后黑屏只有鼠标,没有桌面的解决参考办法

戴尔笔记本开机输入密码后黑屏只有鼠标&#xff0c;没有桌面的解决参考办法 网络常用方法方法一&#xff1a;cmd启动资源管理器方法二&#xff1a;进入安全模式 以上两个方法我的电脑无效&#xff0c;因此我怀疑是启动项的问题更改启动项 网络常用方法 方法一&#xff1a;cmd启…

道路车辆功能安全第2 部分:功能安全管理

道路车辆功能安全 第2 部分&#xff1a;功能安全管理 1 范围 GB/T 34590的本部分规定了应用于汽车领域的功能安全管理的要求&#xff0c;包括&#xff1a; ——独立于项目的关于所涉及组织的要求&#xff08;整体安全管理&#xff09;&#xff1b;及 ——项目特定的在安全生命周…

zip解压文件,可选择保留的文件夹及该文件夹下的所有文件

zip解压文件&#xff0c;可选择保留的文件夹及该文件夹下的所有文件 代码&#xff1a; zip里面的文件&#xff1a; public static void main(String[] args) {// 要解压的ZIP文件路径String zipFilePath "G:\\WeChat\\WeChat Files\\wxid_aff2r4isimwl22\\FileStorage…

司守奎<数学建模算法应用>第二版----第一章习题解答

司守奎<数学建模算法应用>第二版----第一章习题解答 1.1题目代码 1.2题目 1.3题目代码 1.4题目分析代码 1.1 题目 这道题就是简单的一个线性规划模型,不要求我们自行建立,所以就按照书本上的例题去写就行 代码 % 例题1 %使用matlab解决线性规划问题 %目标函数:z3x1-x2…