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

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优化至关重要, 只有知道了被驱动表我们才能进行针对索引进行优化,磨刀不误砍柴工

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

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

相关文章

40基于MATLAB,使用模板匹配法实现车牌的识别。

基于MATLAB&#xff0c;使用模板匹配法实现车牌的识别。具体包括将原图灰度化&#xff0c;边缘检测&#xff0c;腐蚀操作&#xff0c;车牌区域定位&#xff0c;车牌区域矫正&#xff0c;二值化&#xff0c;均值滤波&#xff0c;切割&#xff0c;字符匹配&#xff0c;最终显示车…

codeforces (C++ Doremy‘s Paint 3)

题目&#xff1a; 翻译&#xff1a; 思路&#xff1a; 1、题目意思&#xff1a;将数组中的数进行排列&#xff0c;任意相邻两个数的和都相等&#xff0c;才能说这个数组为好。一下分三种情况讨论。 2、当数组中有三种及三种以上的数字&#xff0c;那任意相邻两个数的和都相等必…

智慧停车视频解决方案:如何让AI助力停车管理升级?

一、项目背景 停车场的管理区域由于面积比较大&#xff0c;进出车辆多&#xff0c;所以在保安方面决不能有任何的麻痹和松懈&#xff0c;继续采用过去保安方式已远远不能满足现代安全防范的需求。为满足停车场的安全和科学系统化管理的需要&#xff0c;以及为了对随时发生的情…

精品Python的定制化图书借阅推荐引擎设计与实现

《[含文档PPT源码等]精品基于Python的定制化图书推荐引擎设计与实现》该项目含有源码、文档、PPT、配套开发软件、软件安装教程、项目发布教程、包运行成功&#xff01; 软件开发环境及开发工具&#xff1a; 开发语言&#xff1a;python 使用框架&#xff1a;Django 前端技…

【持续交付】个人网站

今天给大家演示下如何基于Vuepress尝试持续交付博客网站。 也尝试过其他的方案&#xff0c;比如使用Typora导出html文件&#xff0c;并scp该文件到服务器上。 效果图 该持续交付主流程如下图 提交代码后会触发webHook生成version.txt,部署脚本每分钟轮询一次检测是否存在vers…

物联网和互联网医院小程序:如何实现医疗设备的远程监测和管理?

物联网&#xff08;IoT&#xff09;技术的发展为医疗设备的远程监测和管理提供了巨大的机会。结合互联网医院小程序&#xff0c;我们可以实现对医疗设备的远程访问、监控和管理&#xff0c;从而提高医疗服务的质量和效率。本文将介绍如何实现医疗设备的远程监测和管理&#xff…

漏洞复现-dedecms文件上传(CVE-2019-8933)

dedecms文件上传_CVE-2019-8933 漏洞信息 Desdev DedeCMS 5.7SP2版本中存在安全漏洞CVE-2019-8933文件上传漏洞 描述 ​ Desdev DedeCMS&#xff08;织梦内容管理系统&#xff09;是中国卓卓网络&#xff08;Desdev&#xff09;公司的一套基于PHP的开源内容管理系统&#x…

磁盘调度算法之先来先服务(FCFS),最短寻找时间优先(SSTF),扫描算法(SCAN,电梯算法),LOOK调度算法

目录 1.一次磁盘读/写操作需要的时间1.寻找时间2.延迟时间3.传输时间4.影响读写操作的因素 2.磁盘调度算法1.先来先服务(FCFS)1.例题2.优缺点 2.最短寻找时间优先(SSTF)1.例题2.优缺点3.饥饿的原因 3.扫描算法(SCAN)1.例题2.优缺点 4.LOOK调度算法1.例题2.优点 5.循环扫描算法(…

JDK8新特性:Stream流

目录 1.获取Stream流 2.Stream流常见的中间方法 3.Stream流常见的终结方法 1、 Stream 是什么&#xff1f;有什么作用&#xff1f;结合了什么技术&#xff1f; ●也叫 Stream 流&#xff0c;是Jdk8开始新增的一套 API ( java . util . stream .*)&#xff0c;可以用于操作集…

SpringCloud 微服务全栈体系(七)

第九章 Docker 一、什么是 Docker 微服务虽然具备各种各样的优势&#xff0c;但服务的拆分通用给部署带来了很大的麻烦。 分布式系统中&#xff0c;依赖的组件非常多&#xff0c;不同组件之间部署时往往会产生一些冲突。在数百上千台服务中重复部署&#xff0c;环境不一定一致…

【ICCV2023】频率成分在少样本学习中的重要性

论文标题&#xff1a;Frequency Guidance Matters in Few-Shot Learning 论文链接&#xff1a;https://openaccess.thecvf.com/content/ICCV2023/html/Cheng_Frequency_Guidance_Matters_in_Few-Shot_Learning_ICCV_2023_paper.html 代码&#xff1a;暂未开源 引用&#xff1a;…

入学生活科研随笔

近而立之年&#xff0c;巅峰享受的时期有两段。一是高考后&#xff0c;收到入学通知书。早晨&#xff0c;八点多&#xff0c;我醒来在院子里看到&#xff0c;爸爸在门口和邮政快递员寒暄。那天应该是8月15号&#xff0c;清晨凉凉爽爽的&#xff0c;杨树遮住了大半个院子。第二段…

2-多媒体数据压缩国际标准-Part3

文章目录 视频压缩的国际标准MPEG-1&MPEG-2/H.262视频标准MPEG-4 AVC/H.264视频标准H.264编码框架概述H.264视频编码的技术创新点 H.265/HEVC视频标准HEVC性能与编解码框架概述Quadtree-based coding structureDeblocking & SAO FilterHEVC各模块运算量 视频压缩的国际…

利用Web Serial API实现Vue与单片机串口通信

一、Web Serial API介绍 Web Serial API 是一项 Web 技术&#xff0c;用于在浏览器中访问串行端口设备&#xff08;如 Arduino、传感器等&#xff09;并与之通信。它提供了一组 JavaScript 接口&#xff0c;使得 Web 应用程序可以通过 USB 串行端口连接到硬件设备&…

CentOS7安装配置MobaXterm使用换源处理虚拟机拍照备份与还原Linux常用命令

目录 一、centos7安装与配置 1.1 参考安装步骤 1.2 安装配置CentOS 7实操 1.2.1 配置虚拟机 1.2.2 登录CenOS 1.2.3 检测是否可联网 1.2.4 查看、设置IP地址 1.2.5 使用vi编辑ifcfg-ens33 1.2.6 重启网络服务 1.3 MobaXterm使用 1.3.1 官方下载地址 1.3.2 MobaXte…

BAT035.【工作常用批处理专栏】批处理功能说明及下载

引言:本文主要提供本专栏中练习的批处理功能进行说明和下载。 一、本专栏练习的批处理下载地址 链接:https://pan.baidu.com/s/1L_V-_LojpbfFcUFbvBK1_A 提取码:vady 二、本专栏练习的批处理汇总如下 【工作常用批处理专栏】批处理目录树: │ BAT001.CMD命令速查手册.h…

SonarLint安装与简介

简介&#xff1a; SonarLint 是SonarQube官方推出的可以在idea 静态扫描插件&#xff0c;可以同步sonarqube的规则&#xff0c;在开发编译的时候发现问题&#xff0c;可以有效减少在流水线扫描返工的次数 安装 idea 选择setttings &#xff0c;搜索sonarlint插件&#xff0c…

微信小程序设计之页面文件pages

一、新建一个项目 首先&#xff0c;下载微信小程序开发工具&#xff0c;具体下载方式可以参考文章《微信小程序开发者工具下载》。 然后&#xff0c;注册小程序账号&#xff0c;具体注册方法&#xff0c;可以参考文章《微信小程序个人账号申请和配置详细教程》。 在得到了测…

2023年中国牙钻机优点、产量及市场规模分析[图]

牙钻机&#xff0c;又称为牙科钻机或牙科设备&#xff0c;是一种专用于牙科诊所和牙科医院的医疗设备。它被用来进行牙齿修复、治疗和牙科手术等操作。牙钻机通常由电动马达驱动&#xff0c;带有不同类型的钻头、磨头和其他附件&#xff0c;用于在牙齿上进行各种不同的操作&…

DSP开发例程(3): sys_print_to_uart

目录 DSP开发例程: sys_print_to_uart创建工程源码编辑os.capp.cfgmain.c 调试原理分析 DSP开发例程: sys_print_to_uart 在DSP 应用的执行过程中, 我们经常需要调用 System_printf() 来显示当前的执行状态. 不只是 System_printf() 函数, SYS/BIOS 打印信息的函数还包括: Sys…