MSQL系列(十二) Mysql实战-为什么索引要建立在被驱动表上

Mysql实战-left/right/inner join 使用详解

前面我们讲解了B+Tree的索引结构,也详细讲解下 left Join的底层驱动表 选择原理,那么今天我们来实战一下 left join,right join,inner join 等sql命令,看看到底如何用以及如何建立索引和索引优化

开始之前我们先提一个问题, 为什么索引要建立在被驱动表上 ?

文章目录

      • Mysql实战-left/right/inner join 使用详解
        • 1.建表及测试数据
        • 2. 不用连接查询 笛卡尔积
        • 3.带条件的查询过程即被驱动表的查询过程

1.建表及测试数据

我们先创建两个表 test_user 和 test_order 这两个表作为我们的测试表及测试数据

  • test_user 5条数据, 索引只有主键id
  • test_order 5条数据,索引同样也只有主键id
#创建表 test_user
CREATE TABLE `test_user` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',`id_card` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '身份证ID',`user_name` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名字',`age` int DEFAULT NULL COMMENT '年龄',PRIMARY KEY (`id`),KEY `idx_age` (`age`),KEY `idx_name` (`user_name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户表'
#创建表 test_order
CREATE TABLE `test_order` (`id` int NOT NULL AUTO_INCREMENT,`order_name` varchar(32) NOT NULL DEFAULT '',`user_name` varchar(32) NOT NULL,`pay` int NOT NULL DEFAULT '0',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8

插入数据

#插入 user 用户数据
INSERT INTO `test`.`test_user` (`id`, `id_card`, `user_name`, `age`) VALUES (1, '11', 'aa', 10);
INSERT INTO `test`.`test_user` (`id`, `id_card`, `user_name`, `age`) VALUES (2, '22', 'bb', 20);
INSERT INTO `test`.`test_user` (`id`, `id_card`, `user_name`, `age`) VALUES (3, '33', 'cc', 30);
INSERT INTO `test`.`test_user` (`id`, `id_card`, `user_name`, `age`) VALUES (4, '44', 'dd', 40);
INSERT INTO `test`.`test_user` (`id`, `id_card`, `user_name`, `age`) VALUES (5, '55', 'ee', 50);#插入 order 订单数据
INSERT INTO `test`.`test_order` (`id`, `order_name`, `user_name`, `pay`) VALUES (1, '衣服', 'aa', 100);
INSERT INTO `test`.`test_order` (`id`, `order_name`, `user_name`, `pay`) VALUES (2, '鞋子', 'bb', 200);
INSERT INTO `test`.`test_order` (`id`, `order_name`, `user_name`, `pay`) VALUES (3, '电视', 'cc', 300);
INSERT INTO `test`.`test_order` (`id`, `order_name`, `user_name`, `pay`) VALUES (4, '零食', 'cc', 400);
INSERT INTO `test`.`test_order` (`id`, `order_name`, `user_name`, `pay`) VALUES (5, '衣服', 'cc', 500);

查询结果
在这里插入图片描述

2. 不用连接查询 笛卡尔积

我们先不用 join语句, 直接查询2个表,看下效果

#直接查询2个表
select * from test_user,test_order;

得到的解雇i就是 笛卡尔积

  • user表中的每一条记录,都与order表的一条记录形成组合
  • user中有5条数据,order表中也有5条数据
  • user 的 第一条,分别和 order 5条对应
  • 从而俩个表连接后就有 5 * 5 =25条记录

查询结果笛卡尔积, 25条结果
在这里插入图片描述

3.带条件的查询过程即被驱动表的查询过程

上面我们见识到了 如果没有任何条件,我们连接的2个表会形成笛卡尔积,数量膨胀很大,所以 我们在连接的时候一般都需要过滤条件,我们加一些条件,看下效果

#带条件的 笛卡尔积查询
select * from test_user,test_order where test_user.id > 1 and test_user.id = test_order.id and test_order.pay  >200 ;

执行结果如下, 只有3条
在这里插入图片描述

查询条件如下

  • test_user.id > 1
  • test_user.id = test_order.id
  • test_order.pay > 200
    • 首先 id > 1, 就只剩下 user2,3,4,5
    • 然后test_user.id = test.order.id 这样子就会把很多笛卡尔积 全部去掉, 只保留 两个表 id相同的记录, 还是user的 2,3,4,5
    • 最后还有个 pay>200, 这样就通过掉了 user=2这一条 pay=200, 只保留 3,4,5
    • 也就是我们要的查询结果

我们来分析下执行过程

  1. 确定驱动表,我们先假设 user表是驱动表,然后分析下执行过程
  2. 根据查询条件 test_user.id >1 ,如果 id不是主键, 而且也没索引, 那就是全表扫描ALL, 找到4条记录 user_id = 2,3,4,5
  3. 根据上面驱动表的数据(前面假设是 user), 然后从被驱动表 test_order中寻找匹配的记录,也就是 user_id =2,3,4,5 和 test_user.id = test_order.id匹配的记录
  4. 此时开始查询 test_order,当匹配第一条 test_user.id = 2时, 简化查询条件 test_user.id = test_order.id 就变成了 test_order.id = 2 并且还剩余 一个查询条件 test_order.pay > 200
  5. 所以 test_order 的表就变成了单表查询, 两个查询条件 test_order.id = 2 and test_order.pay >200, 执行test_order的单表查询,查询结果不满足,因为 test_order.id =2 的 pay=200,不pay >200的条件, 本次结束, 继续
  6. 开始下一次 当 user_id =3时, test_order的单表查询变成了 test_order.id =3 and test_order.pay > 200,进行查询, 满足条件,返回结果
  7. 依次类推,直到 user_id 的记录3,4,5匹配完毕 ,最终得到 3条记录
  8. 这就是查询过程

从上面的过程中,我们可以知道,驱动表 只访问了一次
但是被驱动表 要匹配记录,需要不停的去查询,匹配,被动表访问了很多很多次
所以 这就是为什么要把索引建立在被驱动表上的原因


至此,我们通过Mysql的执行查询过程,分析了解到了索引要建立在被驱动表上的原理,这对于我们后期进行SQL分析,有着重要的作用

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

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

相关文章

Leetcode周赛369补题(3 / 3)

目录 1、找出数组的K-or值 - 位运算 模拟 2、数组的最小相等和 - 分情况讨论 3、使数组变美的最小增量运算数 - 动态规划dp 1、找出数组的K-or值 - 位运算 模拟 100111. 找出数组中的 K-or 值 思路: 根据范围,我们可以枚举0~30位,然后在…

【.net core】yisha框架bootstrapTreeTable组件实现行点击事件

YiSha.Web\YiSha.Admin.Web\wwwroot\lib\bootstrap.treetable\1.0\bootstrap-treetable.js文件中替换注册行点击选中事件代码 // 注册行点击选中事件var registerRowClickEvent function () {target.find("tbody").find("tr").unbind();target.find(&quo…

数据库软考知识

分布式数据库透明性 封锁 加上共享锁之后只能加共享锁,加上排他锁之后,啥锁都不能加。 分布式数据库特性 伪传递定理 SQL函数定义,有点冷 来了奥,更冷 存储过程 很重要,下午第二大题也是数据库

Java精品项目源码爱心捐赠平台网站(编号V65)

Java精品项目源码扶农助农平台建设系统(编号V64) 大家好,小辰今天给大家介绍一个爱心捐赠平台网站(编号V65),演示视频公众号(小辰哥的Java)对号查询观看即可 文章目录 Java精品项目源码扶农助农平台建设系统(编号V64)难度指数&a…

【Apache Flink】实现有状态函数

文章目录 在RuntimeContext 中声明键值分区状态通过ListCheckPonitend 接口实现算子列表状态使用CheckpointedFunction接口接收检查点完成通知参考文档 在RuntimeContext 中声明键值分区状态 Flink为键值分区状态(Keyed State)提供了几种不同的原语&…

【洛谷 P1106】删数问题 题解(贪心+字符串)

删数问题 题目描述 键盘输入一个高精度的正整数 N N N(不超过 250 250 250 位),去掉其中任意 k k k 个数字后剩下的数字按原左右次序将组成一个新的非负整数。编程对给定的 N N N 和 k k k,寻找一种方案使得剩下的数字组成…

Arduino驱动ME007-ULA防水测距模组(超声波传感器)

目录 1、传感器特性 2、控制器和传感器连线图 3、驱动程序 3.1、读取串口数据

css:如何通过不同的值,改变盒子的样式和字体颜色通过computed而不是v-if

在使用uniapp编写功能时,可以通过computed方法来实现根据num这个值也可以是后端传过来的值只要是number类型都可以。不同取值来修改盒子的背景颜色和字体颜色。首先,在data中定义一个num来存储当前的值,然后在computed中创建一个样式对象&…

如何在 uniapp 里面使用 pinia 数据持久化 (pinia-plugin-persistedstate)

想要在 uniapp 里面使用 pinia-plugin-persistedstate 会遇到的问题就是 uniapp里面没有浏览器里面的 sessionStorage localStorage 这些 api。 我们只需要替换掉 pinia-plugin-persistedstate 默认的储存 api 就可以了。使用 createPersistedState 重新创建一个实例, 把里面的…

Windows server服务器允许多用户远程的设置

在Windows Server上允许多用户同时进行远程桌面连接,您需要配置远程桌面服务以支持多用户并确保许可证和授权允许多用户连接。以下是在Windows Server上允许多用户远程桌面连接的步骤: 注意:这些步骤适用于 Windows Server 2012、Windows Ser…

开源B2B网站电子商务平台源码下载搭建 实现高效交易的桥梁

随着互联网的普及和电子商务的快速发展,B2B(Business-to-Business)网站电子商务平台在商业领域中发挥着越来越重要的作用。通过开源B2B网站电子商务平台源码搭建,企业可以构建自己的电子商务平台,实现高效交易的桥梁。…

Oracle修改带数据的字段类型

insert into TNW_FUND_SELORG(TFDINFOID,TSOINFOID) select TFD_INFO_ID,TSO_INFO_ID from TFD_SEL_FUNDLINK_TO_OLDFUNDWEB_DB /*修改原字段名*/ ALTER TABLE 表名 RENAME COLUMN 字段名 TO 字段名1; /*添加一个和原字段同名的字段*/ ALTER TABLE 表名 ADD 字段名 VARCHAR…

轻量级 IDE 文本编辑器 Geany 发布 2.0

Geany 是功能强大、稳定、轻量的开发者专用文本编辑器,支持 Linux、Windows 和 macOS,内置支持 50 多种编程语言。 2005 年Geany 发布首个版本 0.1。上周四刚好是 Geany 诞生 18 周年纪念日,官方发布了 2.0 正式版以表庆祝。 下载地址&#…

骨传导耳机优缺点是什么,这几点骨感耳机的利与弊一定得知道!

随着近几年骨感耳机的风头逐渐兴起,骨感耳机受到了不少人的关注,并且存在很多人对于骨感耳机的利与弊还存在着一定的盲点,下面让我来给大家讲解一下。 骨感耳机的利: 1、不入耳的设计对耳道的损伤更小 骨感耳机采用一种独特的声…

好用工具分享 | tmux 终端会话分离工具

目录 1 tmux的安装 2 tmux的基本操作 2.1 启动与退出 2.2 分离会话 2.3 查看会话 2.4 重接会话 2.5 杀死会话 2.6 切换会话 tmux是一个 terminal multiplexer(终端复用器),它可以启动一系列终端会话。 我们使用命令行时,…

vscode免密码认证ssh连接virtual box虚拟机

文章目录 安装软件virtual box配置vscode配置创建并传递密钥连接虚拟机最后 安装软件 安装vscode和virtual box,直接官网下载对应软件包,下载之后,点击执行,最后傻瓜式下一步安装即可 virtual box配置 创建一个仅主机网络的网卡 …

听GPT 讲Rust源代码--library/std(7)

题图来自 Programming languages: How Google is using Rust to reduce memory safety vulnerabilities in Android[1] File: rust/library/std/src/sys/unix/kernel_copy.rs 在Rust的标准库中,kernel_copy.rs文件位于sys/unix目录下,其主要作用是实现特…

Aware接口回调的作用及其意义

Aware接口回调的作用是让Bean获取Spring容器的一些资源或上下文信息,从而更方便地访问其他Bean或资源。 Aware接口包括以下几种: ApplicationContextAware:实现该接口的Bean可以获取到Spring容器的ApplicationContext对象,从而可以…

github搜索技巧探索

毕设涉及到推荐系统,那么就用搜索推荐系统相关资料来探索一下GitHub的搜搜技巧 文章目录 1. 基础搜索2. 限定在特定仓库搜索3. 按照语言搜索4. 按照star数量搜索5. 搜索特定用户/组织的仓库6. 查找特定文件或路径7. 按时间搜索8. 搜索不包含某个词的仓库9. 搜索特定…

stream流—关于Collectors.toMap使用详解

目录 使用规则&#xff1a;1.将list转成以id为key的map&#xff0c;value是id对应的某对象2.假如id存在重复值&#xff0c;则会报错Duplicate key xxx3.想获得一个id和name对应的Map<String, String>3.1 name为空时null3.2 id重复时 4.分组 使用groupingby 使用规则&…