MySQL两个表的亲密接触-连接查询的原理

MySQL对于被驱动表的关联字段没索引的关联查询,一般都会使用 BNL 算法。如果有索引一般选择 NLJ 算法,有 索引的情况下 NLJ 算法比 BNL算法性能更高。

关系型数据库还有一个重要的概念:Join(连接)。使用Join有好处,也会坏处,只有我们明白了其中的原理,才能更多的使用Join。切记不可以:

业务之上,再复杂的查询也在一个连表语句中完成。

敬而远之,DBA每次上报的慢查询都是连接查询导致的,我再也不用了。

连接的本质

我们先来创建两个简单的表,再初始化一些数据

CREATE TABLE t1 (m1 int, n1 varchar(1));CREATE TABLE t2 (m2 int, n2 varchar(1));INSERT INTO t1 VALUES(1, 'a'), (2 , 'b') ,(3 ,'c') ;INSERT INTO t2 VALUES(2 , 'b'), (3 , 'c '),(4 , 'd');

从本质上来说,连接就是把各个表的数据都取出来进行匹配,t1 和 t2 的两个表连接起来就是这样的:

图片

连接语法:

select * from t1, t2;

如果乐意,我们可以连接任意数量的表。但是如果不加任何限制条件的话,这个数据量是非常大的,我们现实中使用都是会加上限制条件的。我们来看下下面这条语句

select * from t1,t2 where t1.m1 > 1 and t1.m1 = t2.m2 and t2.n2 = 'c';

这个连接查询的执行过程大致如下

首先确定第一个需要查询 表称为驱动表(t1)

步骤1中从驱动表 (t1) 中每获得一条记录,都要去被驱动表 (t2) 中查询匹配。

从上面的步骤,可以看出上述的连表查询我们需要查询一次t1,两次t2。也就是说,两表的连接查询中,需要查询一次驱动表,被驱动表需要查询多次。

这里需要注意下,并不是将所有满足条件的驱动表记录先查询出来放到一个地方,然后再去被驱动表中查询,(如果满足条件的驱动表中的数据非常多,那要需要多大的内存呀。) 所以是每获得一条驱动表记录就去被驱动表中查询。

内连接和外连接

我们再来创建两个表,并插入一些数据

CREATE TABLE student ( 
number INT NOT NULL Auto_increment comment'学号',
name varchar (5) COMMENT '姓名',
major varchar (30) comment '专业',
PRIMARY KEY (number));CREATE TABLE score ( 
number INT  comment'学号',
subject varchar (30) COMMENT '科目',
score TINYINT  comment '成绩',
PRIMARY KEY (number, subject));INSERT INTO `student` (`number`, `name`, `major`) 
VALUES ('20230301', '小赵', '计算机科学');
INSERT INTO `student` (`number`, `name`, `major`) 
VALUES ('20230302', '小钱', '通信');
INSERT INTO `student` (`number`, `name`, `major`) 
VALUES ('20230303', '小孙', '土木工程');INSERT INTO `score` (`number`, `subject`, `score`) 
VALUES ('20230301', '高等数学', '60');
INSERT INTO `score` (`number`, `subject`, `score`) 
VALUES ('20230301', '英语', '70');
INSERT INTO `score` (`number`, `subject`, `score`) 
VALUES ('20230302', '高等数学', '80');
INSERT INTO `score` (`number`, `subject`, `score`) 
VALUES ('20230302', '英语', '90');

如果我们想把所有的学生的成绩都查出来,只需要这样执行:

select s1.number, s1.name, s1.major, s2.subject, s2.score from student as s1 , score as s2 
where s1.number = s2.number;

有个问题就是小孙因为某些原因没有参加考试,所以在结果表中没有对应 的成绩记录。如果老师想查看所有学生的考试成绩,即使是缺考的学生 他们的成绩也应该展示出来。

为了解决这个问题,就有了内连接和外连接的概念:

  • 对于内连接的两个表,若驱动表中的记录在被驱动表找不到匹配的记录,则该记录不会加入到最后的结果集。前面提到的连接都是内连接。

  • 对于外连接的两个表,时驱动表中的记录在被驱动表中没有匹配的记录,也仍然需要加入到结果集。

MySQL 中,根据选取的驱动表的不同,外连接可以细分为

  • 左外连接 选取左侧的表为驱动表。

  • 右外连接·选取右侧的表为驱动表。

当我们使用外连接的时候 有时候我们也不想把驱动表的全部记录都加入到最后的结果集中,这个时候我们就要使用过滤条件了。

• WHERE 子句中的过滤条件:不论是内连接还是外连接 凡是不符合 WHERE 子句中过滤条件的记录都不会被加入到最后的结果集。

• ON 子句中的过滤条件:对于外连接的驱动表中的记录来说,如果无法在被驱动表中找到匹配 ON 子句 中过滤条件的记录 那么该驱动表记录仍然会被加入到结果集中,对应的被驱动表记录的各个字段使用NULL 值填充。

所以上述的需求我们可以左查询这样来做:

select s1.number, s1.name, s1.major, s2.subject, s2.score from student as s1 left join score as s2 
on s1.number = s2.number;

语法:

#左连接
select * from t1 left join t2 on '连接条件' where '普通过滤条件'
#右连接
select * from t1 right join t2 on '连接条件' where '普通过滤条件'

内连接的另一种写法,也是常用写法

select s1.number, s1.name, s1.major, s2.subject, s2.score from student as s1 inner join score as s2 
where s1.number = s2.number;

语法:

select * from t1 inner join t2 on '连接条件' where '过滤条件'

连接原理

上述说了这么多,知识简单回顾一下连接,左连接,右连接这些概念。接下来我们重点说一下 MySQL 采用了什么样的算法来进行表与表之前的连接。

Nested-Loop Join (嵌套循环连接) NLJ

前面我们已经介绍过了执行连接查询的大致步骤了,我们再来简单回顾一下

  • 步骤1:选取驱动表,使用相关的过滤条件,选取代价最低的单表访问方法来执行访问。

  • 步骤2:对步骤1中查询到的驱动表结果中的每一条记录,都分别在被驱动表中匹配符合条件的记录。

  • 如果有三个表,那么步骤2中得到的结果集就像是新的驱动表,然后第三个表就成为了驱动表,重复上述的过程。

整个过程就像是一个嵌套循环,所以这种连接方式称为 嵌套循环连接 ,这是最简单也是最笨的一种连接查询算法。大致处理过程如下:

for each row in t1 matching range {for each row in t2 matching reference key {for each row in t3 {if row satisfies join conditions, send to client}}
}

需要注意的是对于获套循环连接算法法来说,每当我们从驱动表中得到了一条记录时,就根据这条记录立时到被驱动表中查询一次,如果得到了匹配的记录, 就把组合后 的记录发送给客户端,然后再到驱动表中获取下一条记录。这个过程将重复进行。

有什么方式可以优化吗

使用索引加快连接速度

这个是我们比较熟悉的方式,也是相对来说最有用的方式,在被驱动表上创建合适的索引,只返回必要的字段等都可以起到一些优化的作用。

Block Nested-Loop Join(块嵌套循环连接)BNL

每次访问被驱动表,其表中的记录都会被加载到内存中,然后再从驱动表中取出一条与其匹配,匹配结束后清楚内存,然后再从驱动表中加载一条记录,然后把被驱动表的记录加载到内存匹配,如果这个被驱动表中的数据特别多而且不能使用索引进行访问,那就相当于要从磁盘上读这个表好多次,这个IO的代价就非常大了。所以我们得想办法,尽量减少被驱动表的访问次数,于是就出现了下面这种方式。

不再是逐条获取驱动表的数据,而是一块一块的获取,引入join buffer 缓冲区, 将驱动表join 相关的部分数据列(大小受join buffer的限制)缓存到 join buffer中,然后开始扫描被驱动表,被驱动表的每一条记录一次性和join buffer中所有的驱动表记录进行匹配(内存中操作)。将简单嵌套循环中的多次比较合并成一次,降低了备驱动表的访问频率。

这里缓存的不只是关联表的列,select后面的列也会缓存起来。所以查询的时候尽量减少不必要的字段,可以让join buffer中可以存放更多的列。

join_buffer_size的最大值在32为系统中可以申请4G,在64为操作系统中可以申请大于4G的空间。

图片

MySQL对于被驱动表的关联字段没索引的关联查询,一般都会使用 BNL 算法。如果有索引一般选择 NLJ 算法,有 索引的情况下 NLJ 算法比 BNL算法性能更高。

关联查询优化总结

  1. 超过三个表禁止 join。【阿里巴巴JAVA开发手册】

  2. 需要 join 的字段,数据类型必须绝对一致;【阿里巴巴JAVA开发手册】

  3. 多表关联查询时,保证被关联的字段需要有索引,尽量选择NLJ算法。【阿里巴巴JAVA开发手册】

  4. 小表驱动大表,写多表连接sql时如果明确知道哪张表是小表可以用straight_join写法固定连接驱动方式,省去mysql优化器自己判断的时间

 

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

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

相关文章

学会使用ubuntu——ubuntu22.04使用WebCatlog

Ubuntu22.04使用WebCatlog WebCatlog是适用于Gnu / Linux,Windows或Mac OS X系统的桌面程序。 引擎基于铬,它用于在我们的桌面上处理Web服务。简单点就是把网页单独一个窗口出来显示,当一个app用。本文就是利用WebCatlog安装后的notion编写的…

第九篇 华为云Iot SDK的简单应用

第九篇 华为云Iot SDK的简单应用 一、华为云Iot SDK API的简单使用 1.初始化SDK 2.绑定连接配置信息 3.连接服务器 4.上报属性 5.接收命令 二、实现智能家居灯光状态上报 🔖以下是上报数据到华为云Iot的代码片段,配合串口控制灯光,改变灯…

Qt —— 自定义飞机仪表控件(附源码)

示例效果 部署环境 本人亲测版本Vs2017+Qt5.12.4,其他版本应该也可使用。 源码1 qfi_ADI::qfi_ADI( QWidget *parent ) :QGraphicsView ( parent ),m_scene ( nullptr )

C++ STL之list的使用及模拟实现

文章目录 1. 介绍2. list类的使用2.1 list类对象的构造函数2.2 list类对象的容量操作2.3 list类对象的修改操作2.4 list类对象的访问及遍历操作 3. list类的模拟实现 1. 介绍 英文解释: 也就是说: list是可以在常数范围内在任意位置进行插入和删除的序列…

yolov8 opencv dnn部署自己的模型

源码地址 本人使用的opencv c github代码,代码作者非本人 使用github源码结合自己导出的onnx模型推理自己的视频 推理条件 windows 10 Visual Studio 2019 Nvidia GeForce GTX 1070 opencv4.7.0 (opencv4.5.5在别的地方看到不支持yolov8的推理,所以只使用opencv…

【机组】计算机组成原理实验指导书.

​🌈个人主页:Sarapines Programmer🔥 系列专栏:《机组 | 模块单元实验》⏰诗赋清音:云生高巅梦远游, 星光点缀碧海愁。 山川深邃情难晤, 剑气凌云志自修。 ​ 目录 第一章 性能特点 1.1 系…

使用js判断list中是否含有某个字符串,存在则删除,

显示上图中使用了两种方式, 左边的是filter将不等于userCode的元素筛选出来组成一个新的list, userCodeList.filter(item> item!userCode);但是上面这个方法在IE浏览器中不支持, 所以改成了右边的方法,使用splice…

web系统架构基于springCloud的各技术栈

博主目前开发的web系统架构是基于springCloud的一套微服务架构。 使用的技术栈:springbootmysqlclickhousepostgresqlredisrocketMqosseurekabase-gatewayapollodockernginxvue的一套web架构。 一、springboot3.0 特性:Spring Boot 3.0提供了许多新特性…

网络安全---防御保护--子接口小实验

子接口小实验: 环境准备: 防火墙区域配置为trust: PC设置其ip为同一个网段: 此时尝试ping无法ping通的原因是没有打开防火墙允许ping,我们在图形化界面允许ping即可 最终结果: .com域名服务器: …

​比特币大跌的 2 个原因

撰文:秦晋 原文来自Techub News:​比特币大跌的 2 个原因 比特币迎来大跌!1 月 23 日凌晨,比特币跌破 40000 美元,为去年 12 月 4 日以来首次,日内跌超 3%。这是自 1 月 10 日美国证监会审批通过 11 只比…

中仕教育:“三不限”事业编的含义

所谓“三不限”,是指在报考事业单位时,对考生的户籍、年龄、学历不作任何限制。所以全国各地的考生只要符合招聘条件,都可以报考。所以每一年的三不限岗位竞争压力都比较大,报考人数都有很多。 ‘三不限’岗位招考信息在哪里看?…

制作Forms表单收集信息

Forms表单收集信息 背景表单制作New FormForms添加元素分享链接 测试查看结果数据结果可视化结果 背景 今天公司老板计划团建旅游,然后呢想让我们投一下票,说让我做一个表单来统计一下公司员工的信息,(前半句不要信啊&#xff09…

基于Apache httpd为windows11搭建代理服务器

文章目录 一.概述二.检查电脑系统类型三.下载安装Apache Httpd四.代理服务配置五.代理服务安装六.报错解决方法七.测试是否运行成功7.1 本机测试7.2 局域网代理测试 八.设置特定ip可访问(阻止其他ip访问)九.参考文档 一.概述 出于某些原因,我…

架构篇22:CAP理论-布鲁尔定理(Brewer‘s theorem)

文章目录 CAP 理论CAP 应用小结 CAP 定理(CAP theorem)又被称作布鲁尔定理(Brewer’s theorem),是加州大学伯克利分校的计算机科学家埃里克布鲁尔(Eric Brewer)在 2000 年的 ACM PODC 上提出的一…

如何在飞书创建企业ChatGPT智能问答助手应用并实现公网远程访问(1)

文章目录 前言环境列表1.飞书设置2.克隆feishu-chatgpt项目3.配置config.yaml文件4.运行feishu-chatgpt项目5.安装cpolar内网穿透6.固定公网地址7.机器人权限配置8.创建版本9.创建测试企业10. 机器人测试 前言 在飞书中创建chatGPT机器人并且对话,在下面操作步骤中…

10个常考的前端手写题,你全都会吗?(下)

前言 📫 大家好,我是南木元元,热爱技术和分享,欢迎大家交流,一起学习进步! 🍅 个人主页:南木元元 今天接着上篇再来分享一下10个常见的JavaScript手写功能。 目录 1.实现继承 ES5继…

11.前端--CSS-背景属性

1.背景颜色 样式名称: background-color 定义元素的背景颜色 使用方式: background-color:颜色值; 其他说明: 元素背景颜色默认值是 transparent(透明)      background-color:transparent; 代码演示: 背景色…

Leetcode—39.组合总和【中等】

2023每日刷题&#xff08;七十六&#xff09; Leetcode—39.组合总和 算法思想 实现代码 class Solution { public:vector<vector<int>> combinationSum(vector<int>& candidates, int target) {vector<vector<int>> ans;vector<int>…

Docker 魔法解密:探索 UnionFS 与 OverlayFS

本文主要介绍了 Docker 的另一个核心技术&#xff1a;Union File System。主要包括对 overlayfs 的演示&#xff0c;以及分析 docker 是如何借助 ufs 实现容器 rootfs 的。 1. 概述 Union File System Union File System &#xff0c;简称 UnionFS 是一种为 Linux FreeBSD NetB…

2024年美赛数学建模思路 - 案例:退火算法

文章目录 1 退火算法原理1.1 物理背景1.2 背后的数学模型 2 退火算法实现2.1 算法流程2.2算法实现 建模资料 ## 0 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 1 退火算法原理 1.1 物理背景 在热力学上&a…