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分析, 索引优化很重要, 因为我们要在 被驱动表上 添加索引,优化提升我们的查询效率

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

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

相关文章

MTSC2023|深圳大会,你关心的技术话题都在这里

MTSC中国互联网测试开发大会 (Make Tester Super Cool, 简称MTSC) 是由国内知名的测试技术社区TesterHome发起的软件测试行业技术会议,大会以“软件质量保障体系和测试研发技术交流”为主要目的,旨在为行业搭建一个深入探讨和交流…

Android NDK开发详解之调试和性能分析的ndk-gdb

Android NDK开发详解之调试和性能分析的ndk-gdb 要求用法选项 NDK 包含一个名为 ndk-gdb 的 Shell 脚本,可以启动命令行原生调试会话。偏好使用 GUI 的用户则应阅读在 Android Studio 中调试这篇文档。 要求 要运行命令行原生调试,必须满足以下要求&am…

【深度学习】Transformer、GPT、BERT、Seq2Seq什么区别?

请看vcr:https://transformers.run/back/transformer/

单链表练习

单链表练习 相关内容: 1.再理解:LNode、*LinkList 2.单链表的整表创建(头插法和尾插法) 3.单链表的读取、插入、删除 4.单链表的整表删除 //单链表的初始化、创建、插入、删除、查找 //结点的结构体:数据域、指针域 …

可靠的互联网兼职平台,平常可以做副业充实生活

在互联网时代,越来越多的人开始通过网络来寻找兼职副业的机会,能够更灵活地安排自己的时间,实现自己的收入增值。那么找到一个正规可靠的线上兼职平台就是一个比较重要的事情,这里分享几个正规靠谱的线上兼职副业平台,…

[推荐]SpringBoot,邮件发送附件含Excel文件(含源码)。

在阅读本文前,可以先阅读我的上一篇文章: SpringBoot,使用JavaMailSender发送邮件(含源码)。 ,本文使用的代码案例涉及到的 jar包、application.properties配置与它相同。 先看一下效果。 图一 图二 在下方代码案例中,…

Redis的四种部署方案

这篇文章介绍Reids最为常见的四种部署模式,其实Reids和数据库的集群模式差不多,可以分为 Redis单机模式部署、Redis主从模式部署、Redis哨兵模式部署、Cluster集群模式部署,其他的部署方式基本都是围绕以下几种方式在进行调整到适应的生产环境…

学习时遇到的错误

1. pycharm中使用ssh远程连接的jupyter时,出现***端口已经被占用的情况 办法一:更换端口,将端口更换为其他 办法二:重启远程终端服务器 2. 关于wandb,在pycharm中调用了wandb.init()初始化函数,中途关闭…

第06章 索引的数据结构

第06章 索引的数据结构 1. 索引及其优缺点 1.1 索引概述 MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。 **索引的本质:**索引是数据结构。你可以简单理解为“排好序的快速查找数据结构”&#xff…

【ROS系列】坐标系转换介绍和对齐

一、坐标系简介 本篇文章介绍:ECEF、ENU、UTM、WGS-84坐标系(LLA) 1.1、ECEF坐标系 ECEF坐标系也叫地心地固直角坐标系。 原点:地球的质心, x轴:原点延伸通过本初子午线(0度经度)和赤道&am…

macOS 创建Flutter项目

参考在 macOS 上安装和配置 Flutter 开发环境 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 这个文档,配置好flutter的环境 编辑器可以选择vscode或者IDEA。 我这里以IDEA为例 打开 IDE 并选中 New Flutter Project。 选择 Flutter,验证 F…

嵌入式Linux系统的闪存设备和文件系统学习纪要

嵌入式Linux系统的闪存设备和文件系统学习纪要 Linux下的文件系统结构如下: NAND Flash 是一种非易失性存储器(Non-Volatile Memory),常用于闪存设备和固态硬盘(SSD)中。以下是几种常见的 NAND Flash 种类&…

中期科技:智慧公厕打造智能化城市设施,提升公共厕所管理与服务体验

智慧公厕是利用先进的技术和创新的解决方案来改进公厕的设施和管理。借助物联网、互联网、5G/4G通信、人工智能、大数据、云计算等新兴技术的集成,智慧公厕具备了一系列令人惊叹的应用功能。从监测公厕内部人体活动状态、人体存在状态,到空气质量情况、环…

【k8s】pod集群调度

调度约束 Kubernetes 是通过 List-Watch **** 的机制进行每个组件的协作,保持数据同步的,每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件,向 APIServer 发送命令,在 Node 节点上面建立 Pod 和 Container。…

注册中心ZK、nameServer、eureka、Nacos介绍与对比

前言 注册中心的由来 微服务架构是存在着很多跨服务调用,每个服务都存在着多个节点,如果有多个提供者和消费者,当提供者增加/减少或者消费者增加/减少,双方都需要感知发现。所以诞生了注册中心这个中间件。 市面上有很多注册中心,如 Zookeeper、NameServer、Eureka、Na…

log4j 日志的简单使用

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 前言 System.out.println("这是我的测…

2023年云栖大会来啦!!(2022年就已经深受震撼)

2023云栖大会已经开始啦,让我们来回顾回顾去年的云栖大会吧。 云栖大会是中国阿里巴巴集团每年举办的一项技术盛会,前身可追溯到2009年的地方网站峰会,2011年演变为阿里云开发者大会,2015年正式更名为“云栖大会”,并且…

暴涨3倍!通过受感染 USB 窃密的事件愈发变多

2023 年上半年,Mandiant 观察到使用受感染 USB 驱动器窃取机密数据的事件至少增加了3倍。此前,Mandiant 披露了在菲律宾的一次攻击行动。本文将会介绍研究人员发现的两外两次基于 USB 驱动器的网络间谍行动。 CSDN大礼包:《黑客&网络安全…

【Verilog】7.2.1 Verilog 并行 FIR 滤波器设计

FIR(Finite Impulse Response)滤波器是一种有限长单位冲激响应滤波器,又称为非递归型滤波器。 FIR 滤波器具有严格的线性相频特性,同时其单位响应是有限长的,因而是稳定的系统,在数字通信、图像处理等领域…

nginx 转发数据流文件

1.问题描述 后端服务,从数据库中查询日志,并生成表格文件返回静态文件。当数据量几兆时,返回正常,但是超过几十兆,几百兆,就会超过网关的连接超时时间30秒。 时序图 这里面主要花费时间的地方在&#xff…