MSQL系列(十) Mysql实战-Join驱动表和被驱动表区分

news2025/1/18 12:03:23

Mysql实战-Join驱动表和被驱动表区分

前面我们讲解了Mysql的查询连接Join的算法原理, 我发现大家都知道小表驱动大表,要让小表作为驱动表, 现在有2个问题

  • 查询多表, 到底哪个是驱动表?哪个是被驱动表, 如何区分?
  • 索引如何优化,到底是加在驱动表上,还是被驱动表上?

今天我们来讨论下这两个问题的答案

文章目录

      • Mysql实战-Join驱动表和被驱动表区分
        • 1.什么是驱动表和被驱动表?
        • 2.Explain命令区分 驱动表及被驱动表
        • 3. left join 左表可能不是驱动表
        • 4. left join 没where 查询 驱动表, 左表才是驱动表
        • 4. left join where 查询条件的表就是驱动表的错误说法
        • 5.left join where查询驱动表判断

1.什么是驱动表和被驱动表?

在join连接查询中,驱动表在SQL语句执行的过程中总是先被读取。而被驱动表在SQL语句执行的过程中总是后被读取。

在读取驱动表数据后,放入到join_buffer后,再去读取被驱动表中的数据来和驱动表中的数据进行匹配。如果匹配成功,就返回结果,否则该丢弃, 继续匹配下一条

为什么要小表驱动大表?
从上面的查询过程中,我们就知道了 , 因为小表查的少, 大大的减少了I/O 次数, join_buffer容量也有限, 表越小, 越少次数匹配, 越容易查结果,所以 我们必须区分 哪个是驱动表, 哪个是被驱动表

现在我们先创建2个表结构, 插入数据,作为测试数据

drop table user_info;
CREATE TABLE `user_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_name` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '用户名',
  `age` int(10)  DEFAULT NULL COMMENT '员工年龄',
  `address` 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='用户表';

drop table order_info;
CREATE TABLE `order_info` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `order_id` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '订单id',
  `user_id` bigint(20) NOT NULL COMMENT '用户user表主键id',
`goods` char(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '商品',
`production` 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='订单表'

INSERT INTO `order_info` (order_id, user_id, goods, production) VALUES (CONCAT("uuid",1), 2, "衣服", "上海贸易");


#插入3条用户数据
INSERT INTO `user_info` (user_name, age, address) VALUES ("张三", 10, "北京");
INSERT INTO `user_info` (user_name, age, address) VALUES ("李四", 20, "上海");
INSERT INTO `user_info` (user_name, age, address) VALUES ("王五", 30, "广州");

#插入2条 张三的 订单记录
INSERT INTO `order_info` (order_id, user_id, goods, production) VALUES ("uuid1", 1, "衣服", "北京三里屯");
INSERT INTO `order_info` (order_id, user_id, goods, production) VALUES ("uuid2", 1, "鞋子", "北京三里屯");
#插入1w条 李四的订单记录, 用存储过程执行

#先创建存储过程
CREATE PROCEDURE test() #创建存储函数;
BEGIN
DECLARE i INT DEFAULT 100;

WHILE i < 10100 DO
	INSERT INTO `order_info` (order_id, user_id, goods, production) VALUES (CONCAT("uuid",i), 2, "书本", "上海贸易");
	SET i = i+1;
end WHILE;

END;
#然后执行 存储过程
CALL test();#调用存储函数

我们可以看下数据是否插入成功
user_info 3条数据
order_info 10002条数据
在这里插入图片描述

2.Explain命令区分 驱动表及被驱动表

对于已有的SQL语句,我们可以直接通过Explain 命令来判断 驱动表与被驱动表, explain命令查看一下SQL语句的执行计划。

输出的执行计划中,首先出现的排在第一行的表是驱动表,排在第二行的表是被驱动表,比如下面的语句

#查看驱动表 第一行就是驱动表
explain
select * from user_info 
left join order_info
on user_info.id = order_info.user_id;

查看执行结果

  • 第一行 user_info表 ,所以驱动表是 user_info
  • 第二行 order_info表, 被驱动表示 order_info
  • 此刻都没有索引信息, type=ALL
  • 即使双方连接字段是 id~user_id, user_info表的id是主键, user_info表也没有走索引
  • 所以驱动表有索引, 也不一定走
    在这里插入图片描述

这里虽然左表示 user_info 是驱动表, 而且是 left_join 查询, 那么我们可以得出结论 left join 左表一定是驱动表么 ?

不能, 重要事情说三遍
!!! left join 左表 不一定是驱动表
!!! left join 左表 不一定是驱动表
!!! left join 左表 不一定是驱动表

3. left join 左表可能不是驱动表

下面我们来验证下 left join 左表不是驱动表的逻辑

我们看下 下面的 查询语句, 也是用 left join 查询, 可以看到 左表是 order left join user_info
那么我们看下 explain 到底哪个是驱动表

#left join 左表不一定是 驱动表
explain
select * from order_info 
left join user_info
on user_info.id = order_info.user_id
where user_info.id = 1;

执行结果

  • left join 左表是 order_info
  • 但是 驱动表是user_info
  • 所以 并不是 left_join 左表就是驱动表
  • 同理 right_join 右表也不一定是驱动表
    在这里插入图片描述

那么 什么情况下? left join 左表示驱动表呢?

4. left join 没where 查询 驱动表, 左表才是驱动表

当SQL查询语句没有 where 查询条件时

  • 没有 where 查询条件时 left join 左表是驱动表, 右表是被驱动表
  • 没有 where 查询条件时 right join 右表是驱动表, 左表示被驱动表
  • 没有 where 查询条件时 inner join 也就是join, mysql自动选择 小表作为驱动表, 大表作为被驱动表,进行底层优化

先说结论, 下面我们验证下这个逻辑

  • 没有 where 查询条件时 left join 左表是order_info, explain 驱动表就是 order_info
  • 没有 where 查询条件时 left join 左表示驱动表, 不管查询表位置如何交换
  • 没有 where 查询条件时 join查询, 不管 左右表顺序, mysql自己优化选择小表作为驱动表

1.没有 where 查询条件时 left join 左表是order_info, explain 驱动表就是 order_info

#没where 查询 左表才是驱动表, 左表是order
explain
select * from order_info 
left join user_info
on user_info.id = order_info.user_id

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

换下位置,看看是否 依旧如此
2.没有 where 查询条件时 left join 左表是user_info, explain 驱动表就是 user_info

#没where 查询  左表才是驱动表, 换位置 左表是user
 explain
select * from user_info 
left join order_info
on order_info.user_id = user_info.id

执行结果, 符合预期
在这里插入图片描述
3.没有 where 查询条件时 , 不管 左右表顺序, join 驱动表是mysql自己优化选择的,小表 user_info就是驱动表, user_info 3条数据, order_info 1w多条数据

#join查询, mysql选择小表作为驱动表
 explain
select * from user_info 
left join order_info
on order_info.user_id = user_info.id

#join'查询, 换下 user_info 和 order_info 的位置
explain
select * from order_info 
join user_info
on user_info.id = order_info.user_id 

user_info不论左侧右侧, 都是小表作为驱动表
执行结果 符合预期
在这里插入图片描述

4. left join where 查询条件的表就是驱动表的错误说法

有where 查询语句时, 驱动表的判断规则是另一种情况
有一种 说法 where查询中只有一个表结构, 那么该表就是驱动表 ?

这种说法是错误的,重要事情说三遍
!!! 有where查询的, where条件的表 就是驱动表 这是错误的
!!! 有where查询的, where条件的表 就是驱动表 这是错误的
!!! 有where查询的, where条件的表 就是驱动表 这是错误的

#带where 查询表, where的表 不是驱动表, 验证错误语法
explain
select * from user_info 
left join order_info
on user_info.id = order_info.user_id
where order_info.user_id = 1;

这是有where 查询条件的, 而且where查询中只有一个表 order_info, 我们来执行下 explain
执行结果, 有where查询条件, order_info,但是 explain的驱动表是 user_info表
在这里插入图片描述
所以上面的说法是靠不住的

5.left join where查询驱动表判断

上面我们验证了 where 查询表就是驱动表这种说法的错误性, 那么 带where查询条件到底哪个是驱动表呢?

我们先说结论,然后验证,结论如下

  • where 查询字段没索引, 那就是谁是左表,用谁
  • where 查询字段有索引, 那就用where表作为驱动表

1.where 查询表字段没索引, 谁是左表,用谁做驱动表
在这里插入图片描述

2.where 查询字段有索引, 那就用where表作为驱动表
在这里插入图片描述


至此, 我们已经了解了 join 语法驱动表及被驱动表的判断,这对于我们进行SQL优化至关重要, 只有知道了被驱动表我们才能进行针对索引进行优化,磨刀不误砍柴工

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

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

相关文章

[Leetcode] 0108. 将有序数组转换为二叉搜索树

108. 将有序数组转换为二叉搜索树 题目描述 给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 高度平衡 二叉搜索树。 高度平衡 二叉树是一棵满足「每个节点的左右两个子树的高度差的绝对值不超过 1 」的二叉树。 示例 1&#xff1a…

【Android内存优化】内存泄露优化之强引用变弱引用完全详解

内存泄露背景 什么是内存泄露 内存空间使用完毕后无法被释放的现象,对于还保持着引用, 该内存不能再被分配使用,逻辑上却已经不会再用到的对象,垃圾回收器不会回收它们。 所以逻辑不再使用的对象,需要释放强引用,以便GC进行回收。 JVM 工作原理 JVM 垃圾回收原理,点…

vlc打开网络流(如rtmp),并查看媒体信息(如编码格式等编码信息)

打开vlc 选择媒体&#xff0c;打开网络串流 输入rtmp地址&#xff0c;点击播放 选择工具-编解码信息 可以查看节目的编码信息什么的

HBuilderX代码变量名称翻译插件

对于许多开发者而言&#xff0c;怎么规范的命名变量是一个非常痛苦的事&#xff0c;而在HBuilderX中有一个的插件可以快速的帮助你完成中文转带格式的变量名&#xff0c;格式可以选择小驼峰、大驼峰、下划线、常量、CSS类名等。 以下为添加此插件的步骤 1、打开插件安装 选择…

Android 类似淘宝的吸顶特效 NestedScrollView+RecycleView

运行图 布局的设计 要实现上面的效果需要搞定NestedScrollView和RecycleView的滑动冲突。有人要问RecycleView为何要滑动自动撑大不就好了么&#xff1f;这个问题其实对于有限的资源加载来说是很好的解决方案&#xff0c;但是如果涉及到的是图文结合的并且有大批量的数据的时候…

牛客题霸 -- HJ52 计算字符串的编辑距离

解题步骤&#xff1a; 参考代码&#xff1a; int main() {string s1;string s2;while (cin >> s1 >> s2){int ms1.size();int ns2.size();//增加空白字符&#xff0c;修正下标的映射关系s1 s1;s2 s2;//多卡一行&#xff0c;多开一列vector<vector<int&…

从零开始开发图床工具:使用 Gitee 和 Electron 实现上传、管理和分享

说在前面 平时写文章或写代码的时候&#xff0c;都少不了需要将本地图片转成在线图片链接&#xff0c;大家都是使用什么工具进行转换的呢&#xff1f;相信很多人都有自己的图床工具&#xff0c;今天来给大家介绍一下&#xff0c;怎么基于Gitee和Electron来开发一个便捷的图床工…

22、Python -- 创建对象和使用对象

目录 构造方法类的作用创建对象操作对象的实例变量操作对象的实例方法增加方法调用方法添加方法删除方法 方法与实例变量总结 构造方法 创建对象 操作实例变量 操作方法 构造方法 构造方法是一个特殊的实例方法&#xff0c;方法名为__init__ 创建对象时&#xff0c;自动调用构…

【手把手教vue会员管理系统】篇四之登录界面

一、登录界面路由配置 1.将view目录下的about、home组件删除&#xff0c;再新建login文件夹&#xff0c;在login文件夹下新建index.vue组件&#xff0c;并添加如下图所示的代码&#xff1a; 2.将App.vue更改成下图所示&#xff0c;删掉不必要的代码。 3.在router的index.js文件…

哈希算法:如何防止数据库中的用户信息被脱库?

文章来源于极客时间前google工程师−王争专栏。 2011年CSDN“脱库”事件&#xff0c;CSDN网站被黑客攻击&#xff0c;超过600万用户的注册邮箱和密码明文被泄露&#xff0c;很多网友对CSDN明文保存用户密码行为产生了不满。如果你是CSDN的一名工程师&#xff0c;你会如何存储用…

项目资源管理案例题

本文来自江山老师高项文档 规划资源管理 没有规划资源管理 资源管理计划项目经理一人制定&#xff0c;没有全员参与 资源管理计划内容不全面&#xff0c;有遗漏 质量工程师编写资源管理计划是不对的 资源管理计划应该各干系人参与&#xff0c;而且还需要经过评审 估算活…

基于元模型优化算法的主从博弈多虚拟电厂动态定价和能量管理MATLAB程序

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 参考文献&#xff1a; 基于元模型优化算法的主从博弈多虚拟电厂动态定价和能量管理_董雷 仿真平台&#xff1a; MATLABcplex 主要内容&#xff1a; 主要为多虚拟电厂/微网的优化调度策略&#xff0c;模型…

实用篇-Nacos配置管理

Nacos不仅具有注册中心的功能&#xff0c;还具有注册管理的功能 一、Nacos实现配置管理 可以使用统一配置管理&#xff0c;来配置更改热更新&#xff0c;整体结构如下 前提条件: 你已经把上面的 实用篇-Nacos注册中心 学完了&#xff0c;并且项目也跟着做了。我们下面会使用到…

Python 接口自动化 —— requests框架

1.前言 Python内置的urllib模块&#xff0c;也可以用于访问网络资源。但是&#xff0c;它用起来比较麻烦&#xff0c;而且&#xff0c;缺少很多实用的高级功能。因此我们使用 requests 模块进行进行接口测试。 requests官方文档资料地址&#xff1a;http://cn.python-request…

操作系统:进程与线程(二)同步与互斥B

一战成硕 2.3.5 管程2.3.6 经典同步问题 2.3.5 管程 管程的特性保证了进程互斥&#xff0c;无需程序员自己实现互斥&#xff0c;降低了死锁发生的可能。 管程的定义 管程是一种高级的同步机制。 定义描述举例 条件变量 2.3.6 经典同步问题 生产者消费者问题 缓冲区没满&a…

会说话,得天下!演讲与口才训练必修课

会说话&#xff0c;得天下&#xff01;演讲与口才训练必修课 口才是现代职场上一项非常重要的素质。有了好的口才&#xff0c;不仅可以很好地展示自己的思想和见解&#xff0c;还可以影响他人并获得支持&#xff0c;这对个人职业发展十分重要。所以&#xff0c;学习如何进行出…

详解 DES加密技术 | 凯撒密码 | 栅栏密码

目录 密码学 恺撒密码 栅栏密码 消息和加密 密码的三个特性 算法和密钥 对称算法 公开密钥算法 DES对称加密技术 DES算法的安全性 DES算法的原理 DES算法的实现步骤 IP置换表和IP-1逆置换表 函数f 子密钥ki S盒的工作原理 DES算法的应用误区 密码学 密码学是一门…

Oracle (7)Online Redo Log Files

目录 一、Oracle Online Redo Log Files及其相关内容介绍 1、Online Redo Log Files简介 2、Online Redo Log Files特点 3、Online Redo Log Files文件组 4、多路复用文件 5、联机重做日志文件工作方式 6、LGWR什么时候写重做 7、LS和LSN 8、删除Redo文件成员 9、删除…

【黑马程序员】mysql基础篇笔记

2023年10月26日12:21:09过一下 1.01.MySQL课程介绍(Av765670802,P1) 2.02. 基础-课程内容&数据库相关概念(Av765670802,P2) 3.03. 基础-概述-MySQL安装及启动(Av765670802,P3) 4.04. 基础-概述-数据模型(Av765670802,P4) 通过表来存储数据的数据库就叫做关系型数据库 …

centos7安装配置以及Linux常用命令

⭐⭐ linux专栏&#xff1a;linux专栏 ⭐⭐ 个人主页&#xff1a;个人主页 目录 一.CentOS的安装 使用vi编辑ifcfg-ens33 二. 下载MobaXterm软件 2.1MobaXterm的用途 2.2 MobaXterm的使用 2.3下载插件vim 三.Linux常用命令 3.4 vi或vim编辑器 3.4.1 命令模式 3.4.2.…