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

news2024/9/28 7:17:08

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.coloradmin.cn/o/1151155.html

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

相关文章

AdaBins:使用自适应bins进行深度估计

论文:https://arxiv.org/abs/2011.14141 代码:https://github.com/open-mmlab/mmsegmentation/tree/main/projects/Adabins 0、摘要 本文主要解决了从单个RGB输入图像估计高质量密集深度图的问题。我们从一个baseline的encoder-decoder CNN结构出发&…

sd模型测试之唐伯虎点秋香

周星驰拍过一个喜剧电影,叫《唐伯虎点秋香》。 其实唐伯虎是一个悲剧人物。 唐伯虎本名唐寅,字伯虎,后改字子畏,号六如居士、桃花庵主、鲁国唐生、逃禅仙吏等,南直隶苏州府吴县人。明代著名画家、书法家、诗人。 他…

iTransformer: INVERTED TRANSFORMERS ARE EFFECTIVE FOR TIME SERIES FORECASTING

#论文题目:ITRANSFORMER: INVERTED TRANSFORMERS ARE EFFECTIVE FOR TIME SERIES FORECASTING #论文地址:https://arxiv.org/abs/2310.06625 #论文源码开源地址:https://github.com/thuml/Time-Series-Library #论文所属会议:Mach…

《RT-DETR改进实战》专栏介绍 专栏目录《限时特惠中》

《RT-DETR改进实战专栏》介绍及目录 介绍:欢迎来到最新专栏《RT-DETR改进实战》!这个专栏专注于基于 YOLOv8 项目的魔改版本,而不是百度飞桨框架中的 RT-DETR。 本专栏为想通过改进 RT-DETR 算法发表论文的同学设计。每篇文章均包含完整的改…

MyBatis-Flex(一):快速开始

框架介绍 MyBatis-Flex 是一个优雅的 MyBatis 增强框架,它非常轻量、同时拥有极高的性能与灵活性。 MyBatis-Flex 官方文档 说明 本文参照官方文档的【快速开始】 章节,编写 Spring Boot 项目的代码示例。 快速开始 创建数据库表 直接参照官网示…

fl studio 21.2.0.3842中文破解版2024最新V21.2完整版免费下载

fl studio 21.2.0.3842中文破解版2024最新V21完整的软件音乐制作环境或数字音频工作站(DAW)宿主软件。FL Studio,常称水果,是一款功能强大的编曲软件,集编曲,录音,剪辑,混音于一身,简单易上手&a…

一文带你彻底弄懂js事件循环(Event Loop)

JavaScript事件循环是JavaScript运行时环境中处理异步操作的机制。它允许JavaScript在执行同步代码的同时处理异步任务,以避免阻塞线程并提供更好的用户体验。 本文将在浏览器异步执行原理基础上带你彻底弄懂js的事件循环机制。 浏览器JS异步执行原理 js是单线程…

envi5.3处理高分二号影像数据辐射定标大气校正

目录 一、多光谱影像处理 1. 辐射定标 2.大气校正 1. 需要准备一些数据: 2.大气校正过程 3、正射校正 二、全色影像处理 1. 辐射定标 2. 正射校正 三、图像融合 1.几何配准 2.图像融合 高分二号处理流程 envi5.3的安装教程: ENVI5.3安装 安装完ENVI5.3后&#xff0…

陪诊系统|挂号陪护搭建二开陪诊师入驻就医小程序

我们的陪诊小程序拥有丰富多样的功能,旨在最大程度满足现代人的需求。首先,我们采用了智能排队系统,通过扫描二维码获取排号信息,让您从繁琐的排队过程中解放出来。其次,我们提供了多种支付方式,不仅可以实…

C++快餐——C++11(2)

如期待奇迹发生,那唯有不停伸手去抓紧,去把握才行。 文章目录 类成员变量缺省值default关键字delete关键字final关键字可变参数模板STL容器中empalce相关接口函数优点 lambda表达式捕获列表注意!!!底层实现 总结 类成员…

第N个斐波那契数列

第N个斐波那契数列 力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 class Solution { public:int tribonacci(int n) {int a[4]{0,1,1,2};if(n<4) return a[n];int kn-3;for(int i0; i<k;i){int tmpa[3];a[3]a[1]a[2]a[3];//不是【0】开始&…

MATLAB——多层小波的重构

%% 学习目标&#xff1a;多层小波的重构 %% 程序1 clear all; close all; load noissin.mat; xnoissin; [C,L]wavedec(x,3,db1); %小波多层分解 ywaverec(C,L,db1); %重构&#xff0c;必须小波类型一致 emax(abs(x-y)) %重构的误差 %% 程序2 clear all;…

基于模拟退火算法的无人机航迹规划-附代码

基于模拟退火算法的无人机航迹规划 文章目录 基于模拟退火算法的无人机航迹规划1.模拟退火搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用模拟退火算法来优化无人机航迹规划。 …

设计模式(全23种)

1.前言 1.CUML类图 面向对象设计主要就是使用UML的类图&#xff0c;类图用于描述系统中所包含的类以及它们之间的相互关系&#xff0c;帮助人们简化对系统的理解&#xff0c;它是系统分析和设计阶段的重要产物&#xff0c;也是系统编码和测试的重要模型依据。下面基于C这门语…

Leetcode970. 强整数

Every day a Leetcode 题目来源&#xff1a;970. 强整数 解法1&#xff1a;枚举 枚举 i 和 j 所有的可能性&#xff0c;然后计算 pow(x, i) pow(y, j)&#xff0c;判断是否 < bound。若满足&#xff0c;则放入一个哈希集合&#xff0c;最后将集合转成数组返回。 第一种…

​轻量应用服务器有什么优势?如何评价亚马逊云科技轻量应用服务器?

什么是轻量应用服务器&#xff1f; 随着如今各行各业对云计算的需求越来越多&#xff0c;云服务器也被越来越多的企业所广泛采用。其中&#xff0c;轻量应用服务器是一种简单、高效、可靠的云计算服务&#xff0c;能够为开发人员、企业和个人提供轻量级的虚拟专用服务器&#…

关于c++unique后会打乱顺序

这为什么加上注释这三行输出就会多个4 5 吗 还是a已经发生了变化? 疑问? 解决: unique要求容器有序&#xff0c;而且执行完以后会把重复的放在后面 因为unique后可能无序所以要排序一下,代码如下 。 源代码 #include <iostream> #include <algorithm> #…

Jina AI 推出全球首款开源 8K 语义向量模型,比肩 OpenAI

作为多模态人工智能技术领域的翘楚&#xff0c;Jina AI 的愿景是铺平通往多模态 AI 的未来之路。今天&#xff0c;Jina AI 在向着该愿景前进的路上&#xff0c;达成了一个重要里程碑。我们正式发布了自主研发的第二代文本向量模型&#xff1a;jina-embeddings-v2&#xff0c;是…

记录一道0xGame 2023 CTF Web ez_unserialize的反序列化漏洞题目收获

ez_unserialize 考点&#xff1a; 1. PHP 的引用来绕过 __wakeup 2.命令行中执行php -r phpinfo();&#xff0c;即可获得完整的phpinfo输出 3.PHP 反序列化 POP 链的构造 源码和代码审计&#xff1a; <?phpshow_source(__FILE__);class Cache {public $key;public $value…