mysql 多表关联执行计划 mysql 多表关联优化

desc SELECT * FROM `expense_application` a left join expense_application_detail b on a.order_no = b.order_no LIMIT 10;

explain SELECT * FROM `expense_application` a left join expense_application_detail b on a.order_no = b.order_no LIMIT 10;

这两种写法是一样的

1、前序
  多表的优化其实是依赖单表的优化,把多个关联表精确到每一个表独自进行优化,可以参考一篇文章。

2、join的匹配机制

  1. Simple Nested-Loop join(NLJ):每次从驱动表获取一条数据,然后去扫描非驱动表的所有数据进行匹配,每扫描一次驱动表就是一次IO,这种效率很低,尤其是非驱动表,这种算法不会使用。
  2. Block Nested-Loop Join:上面第一种算法是每次拿驱动表一条去扫描非驱动表全表,缺点非常的明显,为什么不一次在驱动表拿一批,然后在去扫非驱动表一次呢,所以就出现了这种算法,每次拿驱动表的一批数据,然后去扫一次非驱动表,当然是这一批越大越好了,减少IO,所以就出现了,join buffer缓冲区,适当的增大join buffer是可以提高查询效率的。
  3. Index Nested-Loop Join:要求非驱动表关联字段添加索引,例如 on a.id = b.id ,b.id 字段必须要有索引,a.id可以不添加索引,然后b表会根据a.id去索引查找极大的提高效率。
  4. 前面的1、2两种情况是针对非驱动表关联字段没有加索引的情况下的,如果添加了索引会按照第三种情况去索引查找下面我们来几个sql验证一下(准备了 expense_application 、expense_application_detail两张表)
  5. 执行SQL:desc SELECT * FROM `expense_application` a left join expense_application_detail b on a.order_no = b.order_no LIMIT 10;

        b.order_no没有索引的情况下执行:a.表全表查询,因为没有给查询条件 ,b表现了join buffer 以及 Block Nested-Loop

        b.order_no有索引的情况下执行 :可以看到b表已经使用ref索引

总结:多表关联中小表驱动大表(驱动表数据少非驱动表的IO次数就少)、非驱动表关联字段添加索引

3、确定驱动表

  1. 关于SQL的执行顺序,网上很多人都是说一定是,先ON后WHERE,其实这是不一定的,ON是去非驱动表匹配字段,WHERE是对返回结果进行过滤,先后顺序不会最终的结果有影响的,但是会对查询效率有影响,思考一下,如果驱动表先执行WHERE是不是要去ON匹配的数据就少了,所以驱动表是会先执行WHERE在ON,效率就提高了,这一步MYSQL会自动优化选择的。
  2. 同一个SQL在不同索引生效的情况驱动表是不一样的,MYSQL优化器会自动优化,选择小的表作为驱动表(不是说整个表的数据,是根据SQL查询where之后得到的数据),如果整个SQL都没有WHERE查询条件,驱动顺序就按照SQL原本的来,如果加了where条件,就会优先选择where结果小的表作为驱动表。
  3. 我们来测试一下:执行SQL:desc SELECT * FROM `expense_application` a left join expense_application_detail b on a.order_no = b.order_no LIMIT 10;

        a、没有添加where条件:按照SQL执行顺序来,还是a为驱动表

        b、a.reply_num添加where条件:a为驱动表

        c、b.customer_code添加where条件:这时候b表为驱动表了

        c、b.customer_code和a.reply_num添加where条件:分两种情况

第一种: 根据a.reply_num 查询条件查询出来的数据少,可以看到a.reply_num like 'QC00%' 条件查询出来22条,b.customer_code = '200120'条件查询出来1228条,a为驱动表

第二种: 根据b.customer_code 查询条件查询出来的数据少,可以看到b.customer_code = '200120' 条件查询出来1228条,a.reply_num like 'QC%'条件查询出来7395条,b为驱动表

结论: MYSQL会自动取根据WHERE条件得到最小结果集的表作为驱动表,再去ON非驱动表,所以驱动表先执行WHERE再执行ON,非驱动表先执行ON再执行WHERE,前提条件下是两个表的字段都要命中索引。

 1)所以我们在关联表的时候,可能关联多张表会有相同的字段,我们可以把WHERE条件加在数据集小的表

2)上面说过JOIN关联,非驱动表关联字段要加索引,驱动表不一定加,由上面分析可以知道,驱动表是不固定的,会根据不同索引的生效而改变,所以有可能一个表刚开始是有索引的,后面变成了非驱动表,变成了全表查询,所以我们要根据不同的查询条件,先确定驱动表,更好的优化SQL

3、避免order by 与 group by产生临时表(temporary )

        使用order by的时候,如果能用到索引哪自然是最好的,如果用不到索引就回出现Using filesort,但是这还不是最糟糕的,最糟糕的是出现了Using temporary临时表,效率相当低,说明当前SQL必须要优化了,下面来分析一下

        执行SQL:DESC SELECT * FROM `expense_application` a LEFT JOIN expense_application_detail b ON a.order_no = b.order_no where a.reply_num like 'QC00%' and b.customer_code = '200120' ORDER BY a.reply_num desc 

上面 reply_num 字段用到了所以,索引也用到了range,排序也用到了,算是比较完美的SQL

执行SQL:DESC SELECT * FROM `expense_application` a LEFT JOIN expense_application_detail b ON a.order_no = b.order_no where a.reply_num like 'QC00%' and b.customer_code = '200120' ORDER BY b.customer_code desc 

上面 b.customer_code 字段用到了索引,算是比较完美的SQL

执行SQL:DESC SELECT * FROM `expense_application` a LEFT JOIN expense_application_detail b ON a.order_no = b.order_no where a.reply_num like 'QC00%' and b.customer_code = '200120' ORDER BY a.company_code desc 

  

由于a.company_code字段没有用到索引,所以出现了Using filesort的问题,效率比上面的差了不少

  执行SQL:DESC SELECT * FROM `expense_application` a LEFT JOIN expense_application_detail b ON a.order_no = b.order_no where a.reply_num like 'QC00%' and b.customer_code = '200120' ORDER BY b.cost_item desc 

可以看到出现了Using temporary临时表,所以效率比上面两种更差,主要是根据非驱动表b.cost_item字段进行了排序导致的,个人分析原因如下:

   如果是按照驱动表字段去排序,就会在查询的同时在mysql的server先排序取出数据,然后再去跟非驱动表ON获取关联字段,如果是根据非驱动表去排序,哪么就需要把数据全都取出来,创建临时表,然后放到临时表进行排序,最后再返  回,再销毁临时表

总结:

    1)由上面的结论可以看出,首先确定驱动表非常关键,否则容易出现Using filesort、Using temporary,驱动表变来变去的也没办法优化,可以使用STRAIGHT_JOIN强制指定驱动表,缺点是STRAIGHT_JOIN的结果跟inner join是一样的,会对结果进行过滤,而不是像left join 那样。

    2)如果要优化Using filesort排序字段需要是驱动表的字段,并且添加合理的组合索引,是得排序字段命中索引

    3)如果要优化Using temporary就要把全部的排序字段集中在驱动表上,必要时使用STRAIGHT_JOIN来强制确定驱动表,也许不符合小表驱动大表,但是总体效率还是有提升的

3、多表查询索引的命中情况

  1. 建索引一般都是建组合索引,按照最常用的查询字段,从左往右创建,因为正常情况下一个表只能用上一个索引,用到多个索引可能是出现索引合并的情况或者出现OR查询。
  2. 多个字段的组合索引,在驱动表中会先去根据where去查找,这时候可以命中多个字段的索引,如果是非驱动表,索引只能在ON字段命中,在where里面的情况都是无法命中的,只是对最后的结果集进行过滤
  3. 以上都是个人总结的经验,如有不足,请大佬们指正补充

转自https://blog.51cto.com/u_16099204/7164826

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

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

相关文章

持续拥抱鲲鹏生态 星辰天合深化信创存储能力

近日,鲲鹏昇腾开发者大会与广电五舟“2024 智算中国行”北京站陆续召开,星辰天合持续拥抱鲲鹏生态,以重要的合作伙伴身份受邀参加,并在鲲鹏昇腾开发者大会上荣获“甄选解决方案最佳应用软件奖”,在广电五舟“2024 智算…

C++学习~~string类

1.STL简单介绍 (1)标准模版库,是C里面的标准库的一部分,C标准库里面还有其他的东西,但是我们不经常使用,我们经常使用的还是STL这个标准库部分。 (2)六大件:仿函数&…

Microsoft Threat Modeling Tool 使用(三)

Boundary(边界) 本文介绍信任边界,基于 SDL TM Knowledge Base (Core) 模版,这是一个通用的威胁建模模板,非常适合初学者和大多数威胁建模需求。 这些边界(Boundary)在微软威胁建模工具中用于表…

如何重启Windows系统上的Mysql服务

很久很久之前,我想把我的一台windows笔记本当比服务使用,当时还没有搞wsl, 试了vmware在局域网内总是断连。然后就直接在 windows系统上装了一个 windows版本的Mysql81。 有一天需要修改最大连接数, 费了挺大的劲终于找到了配置文件 my.ini…

在云服务器上运行StyleGAN3生成伪样本

首先是传入数据,这里我们不做赘述。 对于数据格式的裁剪,可以通过以下代码进行: from glob import glob from PIL import Image import os from tqdm import tqdm from tqdm.std import trangeimg_path glob(r"C:\Users\Administrato…

Windows Docker安装运行Nacos

#下载Nacos docker pull nacos/nacos-server #可以创建docker中nacos网络,如果以后要使用docker中的mysql存储nacos配置的话,本文使用本地机器mysql,暂用不到 docker network create nacos_network #暂时先运行docker docker run --nam…

python手写数字识别(PaddlePaddle框架、MNIST数据集)

python手写数字识别(PaddlePaddle框架、MNIST数据集) import paddle import paddle.nn.functional as F from paddle.vision.transforms import Compose, Normalizetransform Compose([Normalize(mean[127.5],std[127.5],data_formatCHW)]) # 使用tran…

农业四情监测站在农业生产中有哪些作用

TH-Q3农业四情监测站是一种先进的农业监测设备,可以对土壤、虫情、气象、苗情、孢子等生产环境状况进行实时动态监控,为农业生产提供全面的数据支持和决策依据。 该监测站通常包括土壤温度、湿度、PH值、电导率等土壤参数传感器,虫情监测仪、…

AI绘图Stable Diffusion,如何无损高清放大图片,保姆级教程建议收藏!

前言 我们在用 stable diffusion 制作AI图片时,默认生成图片的尺寸为512*512,即使是竖图一般也就是512*768,如果再把尺寸设置大一些,就会因为硬件算力不够而造成系统崩溃,今天就来跟大家聊一聊,如何将制作…

Sam Blackshear谈Move如何赋能开发者

Move编程语言提供了直观的编码体验,让开发者能够快速上手。Mysten Labs的联合创始人兼CTO Sam Blackshear创建了Move,这是一种用于编写智能合约的语言,更像传统编程语言,如JavaScript或Rust。 https://youtu.be/iYe_hG8Mzx8 视频…

利用if-else,while-do,case-end,的存储过程

DDL CREATE TABLE student (id INT PRIMARY KEY AUTO_INCREMENT, -- 自增ID作为主键createDate TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, -- 记录创建时间,默认为当前时间userName VARCHAR(255) NOT NULL, -- 用户名,不能为空phone VARCHAR(2…

加速大模型落地,阿里云大模型最新进展

今天在阿里云AI智领者峰会上,阿里云正式发布通义千问2.5,模型性能全面赶超GPT-4 Turbo,成为地表最强中文大模型。同时,通义千问最新开源的1100亿参数模型在多个基准测评收获最佳成绩,超越Meta的Llama-3-70B&#xff0c…

无人机摄影测量数据处理、三维建模及在土方量计算

原文链接:无人机摄影测量数据处理、三维建模及在土方量计算https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247603776&idx2&snd96440e116900a46a71c45ff77316896&chksmfa8217a7cdf59eb15da39dd6366378b98ca39b9c836b76a473ff292b67ee37a6ff6…

从Photoshop到AutoCAD,TeamOS在线预览全搞定:可道云TeamOS系统的在线预览功能深度体验

我们每天都要处理大量的文件,领导发过来的压缩包、同事发来的psd文件等,各种格式的文件杂乱又不好查阅…… 迫切需要一个能够在线预览、管理文件的平台。 初次搭建teamOS 可道云teamOS是一个企业级的在线文件管理平台,支持上百种格式的在线…

Pytest测试实战

Pytest测试框架是动态语言Python专用的测试框架,使用起来非常的简单,这主要得易于它的设计,Pytest测试框架具备强大的功能,丰富的第三方插件,以及可扩展性好,可以很好的和unittest测试框架能够结合起来在项…

启明云端ESP32-S3模组WT32-S3选型,Flash最大可选16MB,PSRAM最大可选8MB

使用ESP32-S3单芯片,可以完成语音连接屏控三合一功能。接下来给大家推荐一款ESP32-S3模组WT32-S3,Flash 最大可选 16MB,PSRAM 最大可选 8MB。核心芯片是ESP32-S3。 2.4GHz Wi-Fi(802.11b/g/n)Bluetooth 5(LE)模组,内置ESP32-S3系列芯片&#…

分析人工智能在智慧银行服务中的实际应用以及面临的挑战

一、引言 近年来,人工智能(AI)技术快速发展,其在金融领域,特别是智慧银行服务中的应用日益广泛。人工智能以其独特的数据处理能力、预测分析能力以及自动化决策能力,极大地提升了智慧银行的服务效率、降低了运营成本,并优化了客户体验。然而,人工智能在智慧银行服务中…

建模:3dmax

3Dmax 制作模型和动画(橘肉); RizomUV 对模型进行展UV(橘皮); Substance Painter 纹理手绘(给橘皮制定想要的皮肤); 1.基础 1.1可编辑多边形、可编辑样条线 体、面都需要…

霍庭格TruPlasma MF 7100 7050电源现货50KW

霍庭格TruPlasma MF 7100 7050电源现货50KW

力扣HOT100 - 416. 分割等和子集

解题思路: 动态规划 对于当前考虑的元素 nums[i],如果 dp[ j - nums[ i ] ] 为 true,说明可以用前面的元素构成和为 j -nums[ i ] 的子集,那么在加上当前元素 nums[ i ] 的情况下,就可以构成和为 j 的子集&#xff0…