SQL性能优化指南:如何优化MySQL多表join场景

目录

多表join问题SQL

这里解释下 Using join buffer (Block Nested Loop):

对性能产生的影响:

三种join算法介绍

join操作主要使用以下几种算法:

(1)Nested Loop Join

(2)Block Nested Loop Join

(3)Index Nested Loop Join

问题定位

DBdoctor SQL审核-识别多表Join问题

总结


多表join问题SQL

对于某个复杂业务场景,通常需要根据多个过滤条件才能拿到两个表中的信息。例如,某开发同事费了半天劲写了一个多表join的SQL实现了功能,但上线后却发现对应接口响应特别慢,通过一步步排查后才定位到问题SQL,SQL如下:


select cell.*, res.pod_name from dbfree.dbins_cell cell right join dbfree.dbins_resource res on 
cell.ip = res.pod_ip where cell.ip in ('10.174.156.14', '10.174.187.144', '10.174.67.11') and
res.path in ('/dev/sdb6', '/dev/sdb5') order by res.namespace;

看下该问题SQL的执行计划:

图片

执行计划中可以看到两个表的type都是ALL,且cell表的Extra中出现 Using join buffer (Block Nested Loop),代表两个表发生了全表扫描,且使用了join buffer。

这里解释下 Using join buffer (Block Nested Loop):

  • Using join buffer:表示 MySQL 在执行JOIN时使用了连接缓冲区。这意味着外层表的部分行被加载到内存中,以便与内层表进行匹配。

  • (Block Nested Loop):指的是 MySQL 使用了块嵌套循环算法,而不是简单的嵌套循环。这种方法优化了JOIN操作,尤其是在内层表没有索引时,能够提高连接的性能。

对性能产生的影响:

  • 内存使用: 使用连接缓冲区意味着 MySQL 会消耗更多内存,因此可以处理更大块的数据,从而减少 I/O 操作并提高性能。

  • 缺乏索引: 这个提示通常表明内层表缺乏合适的索引,导致 MySQL 需要通过全表扫描的方式来处理JOIN操作。虽然 Block Nested Loop比简单的嵌套循环更高效,但相较于使用索引,仍然可能比较慢。

三种join算法介绍

join操作是一种将两个或多个表的行结合起来的方法,本质就是把各个表中的记录都取出来依次匹配的组合加入结果集并返回给用户。

例如SQL:

select * from employee e join department d on e.id = d.employee_id

join操作主要使用以下几种算法:

(1)Nested Loop Join

这是最基本的连接算法,也被称为嵌套循环连接。对于第一个表中的每一行,它会扫描第二个表中的所有行来寻找匹配的行。这种方法的效率通常较低,特别是当表的大小增加时,因为它需要进行大量的磁盘I/O操作。

相当于两个嵌套for循环:


for(employee表行 eRow : employee表){for(department表的行 dRow : department表){if(eRow.id = dRow.emp_id){return eRow;}}
}

图片

例如 employee 表有2行,department表有3行,Nested Loop Join 算法的开销如下:

  • 每一次循环,employee表扫描1次,department表比较3次

  • 共有2次循环,比较 2 * 3 = 6次

MySQL不会简单的使用Nested Loop Join,而是利用buffer,即Block Nested Loop Join。

(2)Block Nested Loop Join

这是一种改进的嵌套循环连接算法,核心思路是减少内层表的扫表次数,它使用了一个叫做连接缓冲区(join buffer)的内存结构来减少磁盘I/O操作。将第一个表按照join_buffer_size的大小进行分块(Block),将每个块作为一批数据放入缓存(而不是单独的一行),它会扫描第二个表中的所有行来寻找匹配的行。这种方法的效率通常比嵌套循环连接要高。

图片

Block Nested Loop Join 算法有以下特点:

  • 当执行计划中的type为ALL、INDEX或RANGE时,可以使用buffer。

  • 可以修改参数optimizer_switch中的block_nested_loop,设置是否开启该算法,默认为on。

    图片

  • 如果buffer大小配置的足够大,可以将employee表的全部数据放入,则department表仅需要扫表1次。join_buffer_size默认大小为256K。

  • 增大buffer_size是一种优化思路,同理,去除不必要的查询字段,减少需要放入buffer中的数据也是一个方向。

  • 在MySQL 8.0.18版本及以后,使用 hash join代替Block Nested Loop Join,基本思想是将驱动表的数据加载到内存(数据大小超过join_buffer_size时加载到磁盘,性能会变差),并建立hash表,这样只需要遍历一次驱动表,然后再去通过hash表寻找匹配的行。

(3)Index Nested Loop Join

这是一种改进的嵌套循环连接算法,核心思路同样是减少内层表的匹配次数,需要关联字段在被驱动表中建立索引。对于第一个表中的每一行,它使用索引来查找第二个表中的匹配行,而不是扫描整个表。这种方法的效率通常比嵌套循环连接要高,但前提是必须有适当的索引。

图片

有了合适的索引后,Index Nested-Loop Join算法可以将匹配次数由 外层表行数 * 内层表行数 减少为 外层表行数 * 内层表索引的高度。

问题定位

综上所述,编写多表join的SQL时,通常的连接优化方向如下:

图片

再回过头来看文章最开头的问题SQL


select cell.*, res.pod_name from dbfree.dbins_cell cell right join dbfree.dbins_resource res on 
cell.ip = res.pod_ip where cell.ip in ('10.174.156.14', '10.174.187.144', '10.174.67.11') and
res.path in ('/dev/sdb6', '/dev/sdb5') order by res.namespace;

可以从以下几个角度排查问题:

  1. 关联字段是否有索引

  2. 若关联字段有索引,索引有没有失效

  3. 小表驱动大表

  4. 不要使用 * 作为查询列,只返回需要的列

经排查发现,被驱动表cell的关联字段ip不存在索引,DBA认为找到问题了,可是给字段cell.ip加上索引后,再次查看执行计划。

图片

咦,驱动表怎么换了?执行计划中第一行为驱动表,第二行为被驱动表。cost优化器认为经过where cell.ip in 条件过滤后的cell表数据更少,更适合作为驱动表。DBA继续给res.pod_ip加索引,再次查看执行计划。

图片

执行计划中type没有all了,但是第二行res表的ref怎么是func?连接条件为等值查询,字段cell.ip和res.pod_ip类型均为varchar,怎么还会有函数操作?

  • func表示索引查找涉及函数或表达式:当你在 JOIN 或 WHERE 子句中使用了函数或表达式(比如字符串函数、日期函数、数学运算等),MySQL 可能无法直接使用索引进行等值匹配,而是会调用某个函数来计算结果。这会导致 MySQL 在执行计划中显示 ref 为 func

DBA没招了,那就用DBdoctor吧,其免费的SQL审核功能可以很方便的发现多表Join的相关问题。

DBdoctor SQL审核-识别多表Join问题

在DBdoctor 3.2.3 版本中,完善了SQL审核的全生命周期覆盖,自动闭环审核出的问题SQL,新增了SQL审核静态规则 300+,其中就有部分和多表join相关的规则。

将问题SQL放入SQL窗口,点击审核。

图片

审核任务报表中出现多表关联,关联字段charset不同,导致索引失效

图片

点击查看审核详情,展示了每条命中规则的解释和建议;除命中规则外,DBdoctor通过自研Cost优化器给出了各个索引的性能分析结果,并基于此推荐了最优索引。

图片

可以看到

  • 问题分析部分,有一条严重问题:多表关联,关联字段charset不同,导致索引失效,关联条件左侧字段ip 的charset为 latin1,右侧字段pod_ip 的charset为 utf8mb4。

那这条sql的问题就非常清楚了,关联字段的charset不一样

开发同学修改cell表的字符集,再次查看执行计划:

图片

可以看到被驱动表type为ref,ref列中使用了索引dbfree.cell.ip,至此问题解决。

但是驱动表中的extra信息出现了Using filesort、Using temporary,详细介绍可参考《一条SQL使用order by,引发IO问题》《MySQL Using temporary案例详解及优化方法》

总结

编写多表join的SQL时,需要注意关联字段是否使用索引、小表驱动大表、适当调整join buffer大小等。DBdoctor 3.2.3版本提供了强大的SQL审核工具,它可以帮助开发者在代码部署前识别并解决潜在的SQL问题。现在,小伙伴们可以免费体验这项功能,提升你的数据库性能和稳定性。立即下载DBdoctor,让你的SQL编写更加高效和安全!

*****************************************************************************

点击了解更多:DBdoctor-1分钟定位数据库性能问题DBdoctor是一款企业级数据库监控、巡检、性能诊断、SQL审核与优化平台,利用eBPF透视数据库内核,可一分钟定位数据库性能问题,实现根因诊断,并给出优化建议。icon-default.png?t=O83Ahttps://www.dbdoctor.cn/?utm=4cf70f49547b4b45864ac76d1da334bf

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

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

相关文章

搭建企业域名服务器案例

任务要求: 某企业要建立一台应用于以下情况的主域名服务器 拥有一个C类网段地址,为202.101.55.0。企业域名注册为company.com。域名服务器的IP地址定位为202.101.55.55,主机名为dns.company.com。企业网通过路由器与Internet连接。要解析的…

第九届清洁能源与发电技术国际学术会议(CEPGT 2024)

第九届清洁能源与发电技术国际学术会议(CEPGT 2024) 2024 9th International Conference on Clean Energy and Power Generation Technology (CEPGT 2024) 【早投稿早录用,享受早鸟优惠】 第九届清洁能源与发电技术国际学术会议&#xff0…

记录一个Ajax发送JSON数据的坑,后端RequestBody接收参数小细节?JSON对象和JSON字符串的区别?

上半部分主要介绍我实际出现的问题,最终下面会有总结。 起因:我想发送post请求的data,但是在浏览器中竟然被搞成了地址栏编码 如图前端发送的ajax请求数据 如图发送的请求体: 很明显是keyvalue这种形式,根本就不是…

开源的键鼠共享工具「GitHub 热点速览」

十一长假回来,我的手放在落灰的键盘上都有些陌生了,红轴竟敲出了青轴般的响声,仿佛在诉说对假期结束的不甘。 假期回归的首更,让我们看看又有什么好玩的开源项目冲上了开源热榜。一套键盘和鼠标控制多台电脑的工具 deskflow&#…

supOS加速数实融合发展

作为工业操作系统领军企业,蓝卓受邀参加2024金砖国家新工业革命伙伴关系论坛,深度参与多个环节。在9月11日召开的金砖国家新工业革命伙伴关系论坛产融合作专题研讨上,蓝卓总经理谭彰分享了supOS在产融协同的最新实践,以及supOS进入…

云上考场小程序+ssm论文源码调试讲解

2 关键技术简介 2.1 微信小程序 微信小程序,简称小程序,英文名Mini Program,是一种全新的连接用户与服务的方式,可以快速访问、快速传播,并具有良好的使用体验。 小程序的主要开发语言是JavaScript,它与…

集师知识付费小程序:打造培训机构在线教育的金字招牌 集师知识付费系统 集师知识付费小程序 集师知识服务系统 集师线上培训系统 集师线上卖课小程序

在数字化浪潮的推动下,在线教育已成为教育领域的热门话题。而在众多在线教育平台中,集师知识付费小程序凭借其独特的定位和创新的模式,成功为培训机构打造了一张闪亮的在线教育金字招牌。 集师知识付费小程序,是一个集课程展示、…

数据分析Power BI设置万为单位的数据

玩过Power BI的同学都知道,power BI在度量值设置单位里,唯独没有万这个单位,但是我们可以自定义,操作过程如下: 1.用DAX新建单位表 单位 SELECTCOLUMNS( { ( "元", 1), ("万",10000), ("千…

面试题:Redis(三)

1. 面试题 背景 问题,上面业务逻辑你用java代码如何写? 2. 缓存双写一致性谈谈你的理解? 3. 双检加锁策略 多个线程同时去查询数据库的这条数据,那么我们可以在第一个查询数据的请求上使用一个 互斥锁来锁住它。 其他的线程走到这…

进程守护化

文章目录 概念引入ps细节展示什么是进程组什么是会话细节演示有关指令的处理 用户级任务和进程组的关系关系不同 什么是守护进程如何创建守护进程 代码说明如何关闭守护进程 问题 概念引入 我们在之前的章节中已将看过进程相关的概念, 本篇介绍守护进程 进程还有进程组, 作业,…

锐龙7 7800X3D与i7-14700K到底怎么选!其实很简单

从2022年的锐龙7 5800X3D到后来的锐龙7 7800X3D,笔者使用X3D处理器已有2年多的时间。站在自己的立场,我是非常希望游戏老鸟购买这类处理器的,并且也推荐了不少。 这里说的是老鸟,也就是比较懂电脑的玩家。 但是对于新手玩家而言&a…

Kali Linux 下载与安装手册

目录 Kali 是什么? 通过Kali官方网站下载 Kali 是什么? Kali Linux,前称BackTrack,是一个基于Debian的Linux发行版,专为数字取证和渗透测试而设计。它由Offensive Security Ltd.开发和维护,旨在为安全专…

HarmonyOS NEXT应用开发实战(二、封装比UniApp和小程序更简单好用的网络库)

网络访问接口,使用频次最高。之前习惯了uniapp下的网络接口风格,使用起来贼简单方便。转战到鸿蒙上后,原始网络接口写着真累啊!目标让鸿蒙上网络接口使用,简单程度比肩uniapp,比Axios更轻量级。源码量也不多…

【Parsec】一款安全高效的远程桌面软件

Parsec 是一款远程桌面软件,它允许用户通过P2P(点对点)技术远程访问和控制另一台计算机。以下是Parsec的一些主要作用、安全私密性特点以及优缺点: 作用: 远程游戏:用户可以远程访问高性能PC进行游戏&am…

记一次pyc逆向

.py文件   源代码文件。   这是开发者编写的 Python 源代码文件,包含了可执行的 Python 代码。 .pyc文件   字节码文件。   Python 源文件(.py)在执行时会被编译为字节码,并存储在 __pycache__ 目录下,文件名通…

Halcon形态学

形态学图像处理(简称形态学)是指一系列处理图像形状特征的图像处理技术。 形态学的基本思想是利用一种特殊的结构元来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。本章节依次对腐蚀,膨胀&#xff0…

Nacos作为注册中心和配置中心

下载安装Nacos 下载地址&#xff1a;Nacos 下载后将这个.zip文件解压 windows系统双击运行startup.cmd 注意事项 一些较新的版本可能会启动时闪退&#xff0c;解决方法为记事本编辑startuo.cmd文件 修改set MODE "standalone" Nacos注册中心 引入依赖 <dep…

动态规划算法专题(六):回文串问题

目录 1、回文子串&#xff08;"引子题"&#xff09; 1.1 算法原理 1.2 算法代码 2、最长回文子串 2.1 算法原理 2.2 算法代码 3、分割回文串 IV&#xff08;hard&#xff09; 3.1 算法原理 3.2 算法代码 4、分割字符串 II&#xff08;hard&#xff09; 4…

Spring Boot教学资源库:开发者的成长之路

2 相关技术简介 2.1Java技术 Java是一种非常常用的编程语言&#xff0c;在全球编程语言排行版上总是前三。在方兴未艾的计算机技术发展历程中&#xff0c;Java的身影无处不在&#xff0c;并且拥有旺盛的生命力。Java的跨平台能力十分强大&#xff0c;只需一次编译&#xff0c;任…

AI视频技术复活老照片-简单快捷

准备老照片 可在网上搜索“老照片”图片&#xff0c;选择人物背景全的图片 照片修复 腾讯的ARC Lab网站 https://arc.tencent.com/zh/ai-demos/faceRestoration 上传照片&#xff0c;修复后下载&#xff0c;会直接在浏览器中下载 AI视频生成 采用可灵网&#xff1a; http…