MySQL进阶-关联查询优化

news2025/3/11 23:05:24

采用左外连接

下面开始 EXPLAIN 分析

EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

结论:type 有All  ,代表着全表扫描,效率较差

 添加索引优化

ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】,可以避免全表扫描
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

可以看到第二行的 type 变为了 ref,rows 也变成了优化比较明显。这是由左连接特性决定的。LEFT JOIN 条件用于确定如何从右表搜索行,左边一定都有,所以 右边是我们的关键点,一定需要建立索引 。  也就是left join 右边所关联的表的关联字段一定要建立索引

 只是对左边的表建立索引的话,是没有效果的,可以通过rows这一列看到,type表要读取的记录仍然是20条。

ALTER TABLE `type` ADD INDEX X (card); #【驱动表】,无法避免全表扫描
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

把右边的表的索引删除,可以发现现在又要走全表扫描了 

DROP INDEX Y ON book;
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` LEFT JOIN book ON type.card = book.card;

 采用内连接

删除先前的索引

drop index X on type;
drop index Y on book;(如果已经删除了可以不用再执行该操作)

换成 inner join(MySQL自动选择驱动表)

EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

 添加索引优化

向book表添加索引后,book自动成为被驱动表,提高了查询效率。

ALTER TABLE book ADD INDEX Y (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

如果新增了type表的索引,此时两个表都有索引,优化器会选择小数据量的表作为驱动表,用来驱动大表。

ALTER TABLE type ADD INDEX X (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM type INNER JOIN book ON type.card=book.card;

对于内连接来说,查询优化器可以决定谁作为驱动表,谁作为被驱动表出现的,接下来把type表的索引删了。可以看到有索引的book表又作为了被驱动表

DROP INDEX X ON `type`;
EXPLAIN SELECT SQL_NO_CACHE * FROM TYPE INNER JOIN book ON type.card=book.card;

 向type表里面添加索引,此时又变成了被驱动表了

ALTER TABLE `type` ADD INDEX X (card);
EXPLAIN SELECT SQL_NO_CACHE * FROM `type` INNER JOIN book ON type.card=book.card;

join语句原理

join方式连接多个表,本质就是各个表之间数据的循环匹配。MySQL5.5版本之前,MySQL只支持一种表间关联方式,就是嵌套循环(Nested Loop Join)。如果关联表的数据量很大,则join关联的执行时间会很长。在MySQL5.5以后的版本中,MySQL通过引入BNLJ算法来优化嵌套执行。

驱动表和被驱动表

驱动表就是主表,被驱动表就是从表、非驱动表。

  • 对于内连接来说:

A一定是驱动表吗?不一定,优化器会根据你查询语句做优化,决定先查哪张表。先查询的那张表就是驱动表,反之就是被驱动表。通过explain关键字可以查看。

SELECT * FROM A JOIN B ON ...
  • 对于外连接来说:
SELECT * FROM A LEFT JOIN B ON ...
# 或
SELECT * FROM B RIGHT JOIN A ON ... 

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

算法相当简单,从表A中取出一条数据1,遍历表B,将匹配到的数据放到result.. 以此类推,驱动表A中的每一条记录与被驱动表B的记录进行判断:

可以看到这种方式效率是非常低的,以上述表A数据100条,表B数据1000条计算,则A*B=10万次。开销统计如下。当然mysql肯定不会这么粗暴的去进行表的连接,所以就出现了后面的两种对Nested-Loop Join优化算法。

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

Index Nested-Loop Join其优化的思路主要是为了减少内存表数据的匹配次数,所以要求被驱动表上必须有索引才行。通过外层表匹配条件直接与内层表索引进行匹配,避免和内存表的每条记录去进行比较,这样极大的减少了对内存表的匹配次数。就是利用索引来提高匹配效率

 

驱动表中的每条记录通过被驱动表的索引进行访问,因为索引查询的成本是比较固定的,故mysql优化器都倾向于使用记录数少的表作为驱动表(外表)。如果被驱动表加索引,效率是非常高的,但如果索引不是主键索引,所以还得进行一次回表查询。相比,被驱动表的索引是主键索引,效率会更高。

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

 之前是将驱动表逐条与非驱动表的记录进行匹配,现在是引入join buffer缓冲区,将驱动表的记录缓冲到缓冲区,然后进行批量匹配,而不是逐条匹配。

Join小结

1、整体效率比较:INLJ > BNLJ > SNLJ

2、永远用小结果集驱动大结果集(其本质就是减少外层循环的数据数量)(小的度量单位指的是表行数 * 每行大小)

select t1.b,t2.* from t1 straight_join t2 on (t1.b=t2.b) where t2.id<=100; # 推荐
select t1.b,t2.* from t2 straight_join t1 on (t1.b=t2.b) where t2.id<=100; # 不推荐

3、为被驱动表匹配的条件增加索引(减少内存表的循环匹配次数)

4、增大join buffer size的大小(一次索引的数据越多,那么内层包的扫描次数就越少)

5、减少驱动表不必要的字段查询(字段越少,join buffer所缓存的数据就越多

Hash Join

从MySQL的8.0.20版本开始将废弃BNLJ,因为从MySQL8.0.18版本开始就加入了hash join默认都会使用hash join

  • Nested Loop:

    对于被连接的数据子集较小的情况,Nested Loop是个较好的选择。

  • Hash Join是做大数据集连接时的常用方式,优化器使用两个表中较小(相对较小)的表利用Join Key在内存中建立散列表,然后扫描较大的表并探测散列表,找出与Hash表匹配的行。

    • 这种方式适合于较小的表完全可以放于内存中的情况,这样总成本就是访问两个表的成本之和。

    • 在表很大的情况下并不能完全放入内存,这时优化器会将它分割成若干不同的分区,不能放入内存的部分就把该分区写入磁盘的临时段,此时要求有较大的临时段从而尽量提高I/O的性能。

    • 它能够很好的工作于没有索引的大表和并行查询的环境中,并提供最好的性能。大多数人都说它是Join的重型升降机。Hash Join只能应用于等值连接(如WHERE A.COL1 = B.COL2),这是由Hash的特点决定的。

 

小结

  • 保证被驱动表的JOIN字段已经创建了索引

  • 需要JOIN 的字段,数据类型保持绝对一致

  • LEFT JOIN 时,选择小表作为驱动表, 大表作为被驱动表 。减少外层循环的次数。

  • INNER JOIN 时,MySQL会自动将 小结果集的表选为驱动表 。选择相信MySQL优化策略。

  • 能够直接多表关联的尽量直接关联,不用子查询。(减少查询的趟数)

  • 不建议使用子查询,建议将子查询SQL拆开结合程序多次查询,或使用 JOIN 来代替子查询。

  • 衍生表建不了索引

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

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

相关文章

fiddler+雷电模拟器(安卓9)+https配置

一、fiddler配置 1、开启https代理 2、根证书安装&#xff1a;导出证书系统安装 二、模拟器设置 1、设置网络桥接模式 【点击安装】提示安装成功后保存即可 2、开启root&#xff08;开启adb远程调试&#xff09; 3、开启磁盘写入 4、设置WLAN代理 5、证书安装&#xff1a;物…

STM32-SPI通信协议

目录 一&#xff1a;什么是通信协议&#xff1f; 二&#xff1a;电路结构 1.硬件电路 2&#xff1a;移位 3&#xff1a;时序图 4.交换字节 三&#xff1a;W25Q64简介 硬件电路&#xff1a;​编辑 存储器地址划分 Dlash操作注意事项 状态寄存器 SPI指令集 四&am…

【CentOS】搭建Radius服务器

目录 背景简介&#xff1a;Radius是什么&#xff1f;Radius服务器验证原理搭建Radius服务器环境信息yum在线安装配置FreeRADIUS相关文件clients.conf文件users文件重启服务 验证 参考链接 背景 在项目中需要用到Radius服务器作为数据库代理用户的外部验证服务器&#xff0c;做…

Vue中自定义指令:ClickOutside(点击当前模块外的位置)

应用场景 假设我们有一个下拉框组件&#xff0c;当下拉框展开的时候&#xff0c;点击下拉框之外的元素可以自动关闭下拉框。 一 ClickOutside代码示例 在vue3中使用ClickOutside // 导入自定义指令 import { ClickOutside as vClickOutside } from element-plus;// 绑定指令…

2019年蓝桥杯第十届CC++大学B组真题及代码

目录 1A&#xff1a;组队&#xff08;填空5分_手算&#xff09; 2B&#xff1a;年号字符&#xff08;填空5分_进制&#xff09; 3C&#xff1a;数列求值&#xff08;填空10分_枚举&#xff09; 4D&#xff1a;数的分解&#xff08;填空10分&#xff09; 5E&#xff1a;迷宫…

jdk-21_linux-x64_bin.tar.gz Linux jdk21压缩包安装保姆级(详细安装教程)

jdk-21_linux-x64_bin.tar.gz 解压版详细安装教程 一、简洁版&#xff08;需要对 Linux 操作有一定基础&#xff09;二、图文详细教程1、前置准备2、解压安装3、配置环境变量4、验证成功 官网下载地址&#xff1a; https://www.oracle.com/java/technologies/downloads/#java2…

第6章 定时器计数器

目录 6.1 定时计数器的结构框图 6.2 定时器的控制字 6.2.1 TMOD&#xff1a;工作方式控制寄存器 6.2.2 定时/计数器控制寄存器TCON 6.3 定时/计数器的4种工作方式 6.3.1 方式0、方式1&#xff08;13位、16位定时计数方式&#xff09; 6.3.2 方式2(常数自动重装入) 6.3.3 方…

回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测

回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测 目录 回归预测 | Matlab实现GWO-BP-Adaboost基于灰狼算法优化BP神经网络结合Adaboost思想的回归预测回归效果基本介绍GWO-BP-Adaboost:基于灰狼算法优化BP神经网络结合Adaboost思想…

蓝桥杯真题0团建dfs+哈希表/邻接表

dfs邻接表储存或者哈希表的运用&#xff0c;考察我们对数据的存储 本题核心就是在求从根节点开始的两棵树相同的最长序列&#xff0c;首先确定用dfs进行深搜&#xff0c;对于节点的形式可以用邻接表&#xff0c;邻接矩阵&#xff0c;哈希表来进行存储数据。下面看代码 邻接表 …

系统架构的评估的系统的质量属性

体系结构苹果可以针对一个体系结构&#xff0c;也可以针对一组体系结构。 体系结构评估过程中&#xff0c;评估人员所关注的是系统的质量属性&#xff0c;所有评估方法所普遍关注的质量属性有以下几个&#xff1a;性能、可靠性&#xff08;容错&#xff0c;健壮性&#xff09;…

论文阅读:基于超图高阶表示的WSI生存预测

Generating Hypergraph-Based High-Order Representations of Whole-Slide Histopathological Images for Survival Prediction 文章目录 论文介绍快速阅读摘要1 引言2 相关工作2.1 生存分析2.2 超图学习的准备工作 3 方法3.1 patch采样和低级特征提取3.2 多超图学习3.2.1 多超…

27. Harmonyos Next仿uv-ui 组件NumberBox 步进器组件禁用状态

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; 文章目录 1. 组件介绍2. 效果展示3. 禁用状态设置3.1 整体禁用3.2 输入框禁用3.3 长按禁用 4. 完整示例代码5. 知识点讲解5.1 禁用状态属性5.2 禁用…

docker无法pull镜像问题解决for win10

docker无法pull镜像问题解决for win10 问题原因分析解决方法 问题 在win10系统上安装好doker-desktop后ping registry-1.docker.io不同&#xff0c;并且也无法登陆hub.docker.com, 使用docker pull xx也无法正常下载 原因分析 hub.docker.com在2024年5月之后&#xff0c;国内…

批量将 Excel 转换 PDF/Word/CSV以及图片等其它格式

Excel 格式转换是我们工作过程当中非常常见的一个需求&#xff0c;我们通常需要将 Excel 转换为其他各种各样的格式。比如将 Excel 转换为 PDF、比如说将 Excel 转换为 Word、再比如说将 Excel文档转换为图片等等。 这些操作对我们来讲都不难&#xff0c;因为我们通过 Office 都…

网络安全之RSA算法

1978年就出现了这种算法&#xff0c;它是第一个既能用于数据加密也能用于数字签名的算法。它易于理解和操作&#xff0c;也很流行。算法的名字以发明者的名字&#xff08;RonRivest&#xff0c;AdiShamir和LeonardAdleman&#xff09;命名。但RSA的安全性一直未能得到理论上的证…

Unity Dots

文章目录 什么是DotsDOTS的优势ECS&#xff08;实体组件系统&#xff09;Job System作业系统Burst编译器最后 什么是Dots DOTS&#xff08;Data-Oriented Technology Stack&#xff09;是Unity推出的一种用于开发高性能游戏和应用的数据导向技术栈&#xff0c;包含三大核心组件…

设计模式-结构型模式-桥接模式

概述 桥接模式 &#xff1a;Bridge Pattern&#xff1a; 是一种结构型设计模式。 旨在将抽象部分与实现部分分离&#xff0c;使它们可以独立变化。 它通过组合代替继承&#xff0c;解决类爆炸问题&#xff0c;并提高系统的灵活性和可扩展性。 组成部分 【抽象部分】&#xff08…

Ultravox:融合whisper+llama实现audio2text交互

Ultravox是由Fixie AI开发的一种创新型多模态大语言模型,专为实时语音交互设计。与传统的语音交互系统不同,Ultravox无需单独的语音识别(ASR)阶段,可以直接理解文本和人类语音,实现更快速、更自然的交互体验。Ultravox v0.5在语音理解基准测试中超越了OpenAI的GPT-4o Realt…

clickhouse集群部署保姆级教程

ClickHouse安装 版本要求 23.8及之后的版本 硬件要求 三台机器 建议配置 磁盘 ssd 500G内存 32gcpu 16c 最低配置 磁盘 机械硬盘 50G内存 4gcpu 4c 容量规划 一亿条数据大约使用1TB磁盘容量 参考官方容量推荐 安装包准备 zookeeper安装 zookeeper需要java启动&…

驾培市场与低空经济无人机融合技术详解

随着科技的飞速发展和社会的不断进步&#xff0c;驾培市场正面临着前所未有的变革。传统汽车驾驶培训已不再是唯一的选择&#xff0c;无人机驾驶等新兴领域正逐渐成为驾培市场的重要组成部分。本报告旨在探讨驾培市场与低空经济的融合发展&#xff0c;特别是应用型人才培养与驾…