【MySQL调优】Join语句优化知识点

相信绝大多数开发者,在开发的项目,因业务和需求逐渐复杂化、多元化后,会增加 Join 语句的使用,但是如果您不太了解 Join语句的规则,也许会逐步的拖垮数据库,乃至整个项目。

今天我们就来分享一下 Join优化的知识点。

Simple Nested-Loop Join

来看一下当进行 join 操作时,MySQL是如何工作的。常见的 join 方式有哪些?

在这里插入图片描述
当进行连接操作时,左边的表是**「驱动表」,右边的表是「被驱动表」**
Simple Nested-Loop Join 这种连接操作是从驱动表中取出一条记录然后逐条匹配被驱动表的记录,如果条件匹配则将结果返回。然后接着取驱动表的下一条记录进行匹配,直到驱动表的数据全都匹配完毕。

「因为每次从驱动表取数据比较耗时,所以MySQL并没有采用这种算法来进行连接操作」

Block Nested-Loop Join

在这里插入图片描述既然每次从驱动表取数据比较耗时,那每次从驱动表取一批数据放到内存中,然后对这一批数据进行匹配操作。这批数据匹配完毕,再从驱动表中取一批数据放到内存中,直到驱动表的数据全都匹配完毕。

批量取数据能减少很多IO操作,因此执行效率比较高,这种连接操作也被MySQL采用。

对了,这块内存在MySQL中有一个专有的名词,叫做 join buffer,我们可以执行如下语句查看 join buffer 的大小。

show variables like '%join_buffer%'

把我们之前用的 single_table 表搬出来,基于 single_table 表创建2个表,每个表插入1w条随机记录

 CREATE TABLE single_table (id INT NOT NULL AUTO_INCREMENT,key1 VARCHAR(100),key2 INT,key3 VARCHAR(100),key_part1 VARCHAR(100),key_part2 VARCHAR(100),key_part3 VARCHAR(100),common_field VARCHAR(100),PRIMARY KEY (id),KEY idx_key1 (key1),UNIQUE KEY idx_key2 (key2),KEY idx_key3 (key3),KEY idx_key_part(key_part1, key_part2, key_part3)
) Engine=InnoDB CHARSET=utf8;create table t1 like single_table;
create table t2 like single_table;

如果直接使用 join 语句,MySQL优化器可能会选择表 t1 或者 t2 作为驱动表,这样会影响我们分析sql语句的过程,所以用 straight_joinMySQL使用固定的连接方式执行查询

select * from t1 straight_join t2 on (t1.common_field = t2.common_field)

运行时间为0.037s

执行计划如下

在这里插入图片描述Extra列中看到了 Using join buffer ,说明连接操作是基于 「Block Nested-Loop Join」 算法

Index Nested-Loop Join

了解了 「Block Nested-Loop Join」 算法之后,可以看到驱动表的每条记录会把被驱动表的所有记录都匹配一遍,非常耗时,能不能提高一下被驱动表匹配的效率呢?
估计这种算法也想到了,就是给被驱动表连接的列加上索引,这样匹配的过程就非常快

在这里插入图片描述
来看一下基于索引列进行连接执行查询有多快?

select * from t1 straight_join t2 on (t1.id = t2.id)

执行时间为0.001秒,可以看到比基于普通的列进行连接快了不止一个档次

执行计划如下

在这里插入图片描述「驱动表的记录并不是所有列都会被放到 join buffer,只有查询列表中的列和过滤条件中的列才会被放入 join buffer,因此我们不要把 * 作为查询列表,只需要把我们关心的列放到查询列表就好了,这样可以在 join buffer 中放置更多的记录」

如何选择驱动表

知道了 join 的具体实现,我们来聊一个常见的问题,即如何选择驱动表?
「如果是 Block Nested-Loop Join 算法:」

  1. 当 join buffer 足够大时,谁做驱动表没有影响
  2. 当 join buffer 不够大时,应该选择小表做驱动表(小表数据量少,放入 join buffer 的次数少,减少表的扫描次数)

「如果是 Index Nested-Loop Join 算法」
假设驱动表的行数是M,因此需要扫描驱动表M行
被驱动表的行数是N,每次在被驱动表查一行数据,要先搜索索引a,再搜索主键索引。每次搜索一颗树近似复杂度是以2为底N的对数,所以在被驱动表上查一行的时间复杂度是
驱动表的每一行数据都要到被驱动表上搜索一次,整个执行过程近似复杂度为

「显然M对扫描行数影响更大,因此应该让小表做驱动表。当然这个结论的前提是可以使用被驱动表的索引」
「总而言之,我们让小表做驱动表即可」
「当 join 语句执行的比较慢时,我们可以通过如下方法来进行优化」

  1. 进行连接操作时,能使用被驱动表的索引
  2. 小表做驱动表
  3. 增大 join buffer 的大小
  4. 不要用 * 作为查询列表,只返回需要的列

来源参考:Fcant

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

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

相关文章

springboot209基于web的大学生一体化服务平台的设计与实现

大学生一体化服务平台的设计与实现 摘 要 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统大学生综合服务信息管…

[计算机网络]---TCP协议

前言 作者:小蜗牛向前冲 名言:我可以接受失败,但我不能接受放弃 如果觉的博主的文章还不错的话,还请点赞,收藏,关注👀支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一 、TCP协…

【数据库】达梦数据库DM8开发版安装

目录 一、达梦数据库概述 1.1 达梦数据库简介 1.2 产品特性 1.3 产品架构 二、安装前准备 2.1 新建 dmdba 用户 2.2 修改文件打开最大数 2.3 挂载镜像 2.4 新建安装目录 2.5 修改安装目录权限 三、数据库安装 3.1 命令行安装 3.2 配置环境变量 四、配置实例 4.1…

【Leetcode】889. 根据前序和后序遍历构造二叉树

文章目录 题目思路代码结果 题目 题目链接 给定两个整数数组,preorder 和 postorder ,其中 preorder 是一个具有 无重复 值的二叉树的前序遍历,postorder 是同一棵树的后序遍历,重构并返回二叉树。 如果存在多个答案,…

世界顶级名校计算机专业学习使用教材汇总

🌈个人主页: Aileen_0v0 🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​💫个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-IauYk2cGjEyljid0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

臻图信息:让数字孪生“智慧”赋能防汛工作,面对应急事件更加从容

近年来随着极端天气的频发,对城市来说,高强度、连续性、时空分布不均匀的降水,容易发生城市内涝、交通堵塞、桥梁建筑损毁、河水倒灌等其他自然灾害。自然灾害主要包括地震、洪涝、台风、泥石流等,灾害的发生不仅对财产造成巨大损…

冷链物流追踪:Java与MySQL的协同实践

✍✍计算机编程指导师 ⭐⭐个人介绍:自己非常喜欢研究技术问题!专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目:有源码或者技术上的问题欢迎在评论区一起讨论交流! ⚡⚡ Java实战 |…

国际网络专线多少钱一年

国际网络专线作为企业扩展业务的重要通信渠道,已经成为许多企业不可或缺的选择。然而,对 于许多企业来说,选择一条稳定、高质量的国际网络专线,并不是一件容易的事情。那么,国际 网络专线到底多少钱一年呢?…

【动态规划】代码随想录算法训练营第三十八天 |基础知识,509.斐波那契数,70.爬楼梯,746.使用最小花费爬楼梯(待补充)

基础知识: 题目分类大纲如下: 算法公开课 《代码随想录》算法视频公开课(opens new window):动态规划理论基础(opens new window),相信结合视频再看本篇题解,更有助于大家对本题的理解。 #什么是动态规划 动态规划…

Java之线程:线程的创建、实现、方法及现成的状态

线程基础 程序、进程、线程? 程序: ​ 程序是含有指令和代码的文件,被存储在磁盘或其他数据存储设备中,可以理解为程序是包含静态代码的文件。例如,浏览器软件,游戏软件等软件的安装目录和文件 进程&…

SQL注入漏洞解析

什么是SQL注入 原理: SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服…

在vue3中使用canvas实现雨滴效果

在vue3中使用canvas实现雨滴效果 这是封装的一个组件DotAndRain&#xff08; &#xff09; <script setup> import { ref, onMounted } from "vue"; import { onUnmounted } from "vue";let animationFrameId null;const el ref(null); let canv…