MSQL系列(十一) Mysql实战-Inner Join算法底层原理及驱动表选择

Mysql实战-Inner Join算法驱动表选择

前面我们讲解了B+Tree的索引结构,及Mysql的存储引擎MyISAM和InnoDB,也详细讲解下 left Join的底层驱动表 选择, 并且初步了解 Inner join是Mysql 主动选择优化的驱动表,知道索引要建立在被驱动表上

那么对于Inner join 来说, 到底什么是小表?

文章目录

      • Mysql实战-Inner Join算法驱动表选择
        • 1.建表及测试数据
        • 2. inner join where条件不一致,判断大小表
        • 3. inner join小表 select字段不一致,判断大小表

1.建表及测试数据

我们先创建几乎一样的表结构用来测试 testA和testB,

  • testA 4条数据, 索引只有主键id
  • testB 6条数据, 索引只有主键id

drop TABLE IF EXISTS testA;
CREATE TABLE `testA` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_name` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='测试表A';

drop TABLE IF EXISTS testB;
CREATE TABLE `testB` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `hero_name` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '英雄名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='测试表B';

#插入测试数据 testA 4条数据
INSERT INTO `testA` (user_name) VALUES ("张三");
INSERT INTO `testA` (user_name) VALUES ("李四");
INSERT INTO `testA` (user_name) VALUES ("王五");
INSERT INTO `testA` (user_name) VALUES ("吕布");

#插入测试数据 testB 10条数据
INSERT INTO `testB` (hero_name) VALUES ("亚瑟");
INSERT INTO `testB` (hero_name) VALUES ("鲁班");
INSERT INTO `testB` (hero_name) VALUES ("妲己");
INSERT INTO `testB` (hero_name) VALUES ("大乔");
INSERT INTO `testB` (hero_name) VALUES ("小乔");
INSERT INTO `testB` (hero_name) VALUES ("黄忠");
INSERT INTO `testB` (hero_name) VALUES ("元芳");
INSERT INTO `testB` (hero_name) VALUES ("后羿");
INSERT INTO `testB` (hero_name) VALUES ("马克");
INSERT INTO `testB` (hero_name) VALUES ("吕布");

查看插入结果, 符合预期
在这里插入图片描述

2. inner join where条件不一致,判断大小表

我们知道 join 是where自己选择的驱动表, 选择小表 作为驱动表, 如何判断小表?

  • 那么到底什么是小表呢?
  • 是否是数据量小的表一定是小表?
  • 跟索引是否有关系?

下面我们来解决这些问题

Mysql这里对于大小的判断,是指真正参与关联查询的数据量所占用的join_buffer的大小来区分的, 不是根据表中所有的数据行数来判断的

所以说不是数据量小的表 就是小表

我们用实例来验证下

#inner join where条件不一致 导致的 驱动表不一致
explain select * from testB as b inner join testA as a on a.id = b.id where b.id > 1;
explain select * from testB as b inner join testA as a on a.id = b.id where b.id > 9;

执行结果
在这里插入图片描述
结果分析

  • 同样的SQL语句, 只有条件不一样, 就会导致 不同的驱动表
  • 第一条 inner join SQL 驱动表是 A
  • 第二条 inner join SQL 驱动表是 B
  • 表A和表B的 结构是一样的, 所以加载到 join_buffer的东西大小也是一样的
  • 当 id > 1的时候, B表经过where条件过滤后,有10行数据参与join操作, 所以B表数据 10条, 这时候 A全部表也就4条数据, 所以A就是 小表, 驱动表就是A
  • 当 id > 9的时候, B表经过where条件过滤后,有2行数据参与join操作, , 而A表全部数据是4条, 这时候B 就是小表, 驱动表就是B
  • 所以不是数据总行数决定驱动表,而是经过过滤后, 参与到join操作的数据 来决定大小表
3. inner join小表 select字段不一致,判断大小表

上面我们看到了 都是select * 表结构一致, 查询where条件不一致导致的 驱动表不一致的情况, 那么还有其他情况影响驱动表么?

当然有, select 后面查询字段也会影响到 大小表 驱动表的判断,因为 join buffer 判断的就是查询的字段 加载进内存
我们再建一个表用来测试,该表字段较多

#创建testC表
drop TABLE IF EXISTS testC;
CREATE TABLE `testC` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `emp_name` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '人名',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='测试表C';

#创建testD表
drop TABLE IF EXISTS testD;
CREATE TABLE `testD` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `emp_name1` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '人名1',
  `emp_name2` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '人名2',
  `emp_name3` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '人名3',
  `emp_name4` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '人名4',
  `emp_name5` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '人名5',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='测试表C';

#testC 插入2条数据
INSERT INTO `testC` (emp_name) VALUES ("亚瑟1");
INSERT INTO `testC` (emp_name) VALUES ("鲁班1");

#testC 插入2条 很多列的数据
INSERT INTO testD (emp_name1, emp_name2, emp_name3, emp_name4,emp_name5) VALUES ("1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111","1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111");
INSERT INTO testD (emp_name1, emp_name2, emp_name3, emp_name4,emp_name5) VALUES ("2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222","2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222","2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222","2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222","2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222");

查看结果,符合预期, C,D表都是2条数据
在这里插入图片描述

现在我们使用testB和testC, testD 我们来验证下 select 的列 对大表小表的影响

  • testC 表只有2列, 列属性都是char(32)
  • testD 表有5列, 列属性都是varchar(500)
  • 按照 join_buffer 加载逻辑, 相同条件下( 行数一样) 只要是查了 testD的列, 他的列比较大, 占空间比较多, 就是大表
  • 计算占用join_buffer 空间大小 = 查询的字段数 * 参与join的行数 * 每个字段的空间大小
  • 占用的空间大小
  • 所以对于testC和testD 只要查了D的列, D列多,字段多,空间大, 就是大表
  • 这种情况下 驱动表是小表, 就应该是 testC C表

看下我们分析的结果

#inner join select字段不一致 导致的 驱动表不一致, 字段多的空间大, 就是大表
explain select d.* from testC as c inner join testD as d on c.id = d.id ;

执行结果, 的确 查询了testD的列, 字段多, 占用 join_buffer 空间大, 就是大表, 所以驱动表就选择 小表 testC, 符合预期
在这里插入图片描述

那如果我们查询testC的列呢? 应该如何选择驱动表?

  • testC 表只有2列, 列属性都是char(32)
  • testD 表有5列, 列属性都是varchar(500)
  • 查询 testC的列, 那么加载进 join_buffer的就是 c的全部列
  • 对于 testD来说,加载进 join_buffer的就是 d的主键id 列, 因为 on条件 关联的是 c.id = d.id
  • 所以 d只有id列, c是全部列, c就是大表, d就是小表, d就是驱动表
#inner join select字段不一致 导致驱动表不一致, 查询 字段少的
#加载进join_buffer的 testC全字段,testD只有id字段, 那就是testD 占空间少, 驱动表就是d 
explain select c.* from testC as c inner join testD as d on c.id = d.id;

explain 执行结果 ,看到 d就是驱动表, 符合预期
在这里插入图片描述


至此, 我们彻底的了解了 inner join算法驱动表的选择, 也了解了 mysql如何选择驱动表, 如何选择小表, 这对于我们后期SQL分析, 索引优化很重要, 因为我们要在 被驱动表上 添加索引,优化提升我们的查询效率

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

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

相关文章

【java学习—十】操作集合的工具类Collections(8)

文章目录 1. 操作集合的工具类: Collections2. 应用3. 查找、替换3.1. max 与 min3.2. 根据Comparator返回max(min) 3.3. frequency 与 replaceAll4. 同步控制 1. 操作集合的工具类: Collections Collections 是一个操作 Set 、List 和 Map 等集合的工具…

揭示沉浸式展览设计方案中的创新展示技术

随着数字多媒体技术在展览设计方案中的广泛应用,让传统的静态展示方式,走向了更为生动、立体的动态化设计模式,而其中最令人瞩目的当属沉浸式展览展示,它以其独特的展示方式和引人入胜的体验效果,引发了大量的关注和热…

解决找不到msvcr120.dll无法继续执行问题的5个方法,快速解决dll问题

在计算机使用过程中,我们经常会遇到一些错误提示,其中之一就是找不到msvcr120.dll的错误。这个错误通常发生在运行某些程序或游戏时,它会导致程序无法正常启动或运行。那么,如何解决找不到msvcr120.dll的问题呢?下面我…

深度学习数据集大合集—疾病、植物、汽车等

最近又收集了一大批深度学习数据集,今天分享给大家!废话不多说,直接上数据! 1、招聘欺诈数据集 招聘欺诈数据集:共收集了 200,000 条数据,来自三个网站。 该数据集共收集了 200.000 条数据,分别…

HackTheBox-Starting Point--Tier 1---Tactics

文章目录 一 题目二 实验过程三 Psexec工具使用 一 题目 Tags Network、Protocols、SMB、Reconnaissance、Misconfiguration译文:网络、协议、中小企业、侦察、配置错误Connect To attack the target machine, you must be on the same network.Connect to the S…

自动化测试实战篇:UI自动化测试用例管理平台搭建

用到的工具:python3 django2 mysql RabbitMQ celery selenium python3和selenium这个网上很多教程,我不在这一一说明; 平台功能介绍: 项目管理:用于管理项目。每个项目可以设置多个环境,例如开发环境…

怎样才知道一个单片机的性能到极限了?

怎样才知道一个单片机的性能到极限了? 就题主的问题,应该是想问CPU利用率的问题。可以看看Rt-thread中关于统计CPU利用率函数,其主要实现方式是在idle线程先关闭中断计数后,正常计数(可被其他线程打断),最近很多小伙伴…

竞赛知识点11【线段树】

文章目录 一、概念二、基本操作2.1、建树2.2、区间询问操作2.3、单点修改2.4、区间修改一、概念 线段树是用一种树状结构来存储一个连续区间的信息的数据结构。 它主要用于处理一段连续区间的插入,查找,统计,查询等操作。 复杂度: 设区间长度是 n n n,所有操作的复杂度是 l…

java修仙基石篇->instanceof子父类检查

instanceof检查子父类(或者是否能被强转) 作用1:检查某对象是否是某类的子类 如:儿子类继承了父亲类。 检查儿子类对象是否属于父亲类 作用2:检查两个对象是否可以强转 语法: 子类对象 instanceof 父…

蚂蚁蚁盾发布实体产业「知识交互建模引擎」,最快10分钟定制AI风控模型

数字化起步晚、数据分散稀疏、专业壁垒高、行业知识依赖「老师傅」,是很多传统产业智能化发展面临的难题。2023年云栖大会上,蚂蚁集团安全科技品牌蚁盾发布“知识交互建模引擎”,将实体产业知识与AI模型有机结合,助力企业最快10分…

【23真题】Top3简单专业课似双非!

今天分享的是23年复旦大学957的信号与系统试题及解析。 本套试卷难度分析:这套卷子平均分为120左右,最高分145分。22年复旦大学957信号与系统,我也发布过,若有需要戳这里自取!本套试题内容难度中等偏下,说…

主播直播美颜SDK:性能优化策略

当下,主播直播美颜SDK成为了越来越多主播的利器。这些SDK可以实时美化主播的外貌,提高视觉吸引力,但同时也需要处理大量的图像数据。因此,性能优化成为了不可或缺的一环。本文将探讨主播直播美颜SDK的性能优化策略,以确…

【详细教程】关于如何使用GitGitHub的基本操作汇总GitHub的密钥配置 ->(个人学习记录笔记)

文章目录 1. Git使用篇1.1 下载安装Git1.2 使用Git 2. GitHub使用篇2.1 如何git与GitHub建立联系呢?2.2 配置公钥 1. Git使用篇 1.1 下载安装Git 点击 官网链接 后,进入Git官网,下载安装包 然后根据系统类型进行下载,一般为wind…

如何修改MinIO Share时的URL

使用Helm方式在Kubernetes中部署MinIO后。选择分享文件,获得的分享连接域名为K8S内部Service连接地址,这样的地址不可以在集群外部使用。 修改MINIO_SERVER_URL 前置条件 (Helm部署方式)域名需要访问到Name为minio的K8S Service…

ReuseAndDiffuse笔记

https://arxiv.org/pdf/2309.03549.pdf https://mp.weixin.qq.com/s/pbSK4KOO2hqQU1-uwQzjBA 数据集: BLIP-2、MiniGPT4 等多模态大语言模型,对Moments-In-Time、Kinetics-700 和 VideoLT等数据集进行自动标注; Image-text datasets:平移缩…

《低代码指南》——维格云机器人常见报错怎么解决?

在使用维格机器人调用维格表的API过程中,可能会出现机器人执行结果未达到预期的情况,此时可能是机器人运行出现了问题;通过点击这个机器人右上角的“运行历史”可以查看运行记录,通过对运行记录的分析,可以推断出问题所在,然后进行修改。 而对于运行历史的分析,主要是针…

C语言——判断 101-200 之间有多少个素数,并输出所有素数

完整代码&#xff1a; // 判断 101-200 之间有多少个素数&#xff0c;并输出所有素数 #include<stdio.h>//判断一个数n是否为素数 int isPrimeNumber(int n){//1不是素数if (n1){return 0;}for (int i 2; i <(n/2); i){//当有n能被整除时&#xff0c;不是素数if ((n…

【ES专题】ElasticSearch 高级查询语法Query DSL实战

目录 前言阅读对象阅读导航前置知识数据准备笔记正文一、ES高级查询Query DSL1.1 基本介绍1.2 简单查询之——match-all&#xff08;匹配所有&#xff09;1.2.1 返回源数据_source1.2.2 返回指定条数size1.2.3 分页查询from&size1.2.4 指定字段排序sort 1.3 简单查询之——…

LTD249次升级 | 官微名片可编辑微信二维码 • 商城可图标展示商品分类 • 应用引擎改进导入功能、可批量导入图片文件

1、 官微名片支持编辑微信二维码、传真号等&#xff1b; 2、 新增商城分类列表功能页&#xff1b; 3、 应用引擎支持图片字段批量导入&#xff1b; 4、 官微中心功能优化&#xff1b; 5、 已知问题修复与优化&#xff1b; 01 官微名片(平台版) 1) 首页布局与样式优化 在本次…

树结构及其算法-二叉树遍历

目录 树结构及其算法-二叉树遍历 一、中序遍历 二、后序遍历 三、前序遍历 C代码 树结构及其算法-二叉树遍历 我们知道线性数组或链表都只能单向从头至尾遍历或反向遍历。所谓二叉树的遍历&#xff08;Binary Tree Traversal&#xff09;&#xff0c;简单的说法就是访问树…