一、Join查询原理

MySQL内部采用了一种叫做 nested loop join(嵌套循环连接)的算法:通过驱动表的结果集作为循环基础数据,然后一条一条的通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。如果还有第三个参与 Join,则再通过前两个表的 Join 结果集作为循环基础数据,再一次通过循环查询条件到第三个表中查询数据,如此往复,基本上MySQL采用的是最容易理解的算法来实现join

所以驱动表的选择非常重要,驱动表的数据小可以显著降低扫描的行

一般情况下参与联合查询的两张表都会一大一小,如果是join,在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表。简单来说,驱动表就是主表,left join 中的左表就是驱动表,right join 中的右表是驱动表。

二、Nested-Loop Join

如 select * from t1 inner join t2 on t1.id=t2.tid ,t1称为外层表,也可称为驱动表,t2称为内层表,也可称为被驱动表

mysql只支持一种join算法:Nested-Loop Join(嵌套循环连接),但Nested-Loop Join有三种变种:

  • 简单嵌套循环连接:Simple Nested-Loop Join(SNLJ)
  • 索引嵌套循环连接:Index Nested-Loop Join(INLJ)
  • 缓存块嵌套循环连接:Block Nested-Loop Join(BNLJ)

在选择Join算法时,会有优先级,理论上会优先判断能否使用INLJ、BNLJ: Index Nested-LoopJoin > Block Nested-Loop Join > Simple Nested-Loop Join

2.1 Simple Nested-Loop Join

如下图,r为驱动表,s为匹配表,可以看到从r中分别取出r1、r2、…、rn去匹配s表的左右列,然后再合并数据,对s表进行了rn次访问,对数据库开销大。

如果table1有1万条数据,table2有1万条数据,那么数据比较的次数=1万 * 1万 =1亿次,这种查询效率会非常慢。

故基本不使用这种方式,mysql会根据情况选择其他两种方式进行查询

2.2 Index Nested-Loop Join(减少内层表数据的匹配次数)

  • 索引嵌套循环连接是基于索引进行连接的算法,索引是基于内层表的,通过外层表匹配条件直接与内层表索引进行匹配,避免和内层表的每条记录进行比较, 从而利用索引的查询减少了对内层表的匹配次数,优势极大的提升了 join的性能
  • 使用场景:只有内层表join的列有索引时,才能用到Index Nested-LoopJoin进行连接
  • 由于用到索引,如果索引是辅助索引而且返回的数据还包括内层表的其他数据,则会回内层表查询数据,多了一些IO操作

这个要求非驱动表(匹配表s)上有索引,可以通过索引来减少比较,加速查询。

在查询时,驱动表(r)会根据关联字段的索引进行查找,当在索引上找到符合的值,再回表进行查询,也就是只有当匹配到索引以后才会进行回表查询。

如果非驱动表(s)的关联健是主键的话,性能会非常高,如果不是主键,要进行多次回表查询,先关联索引,然后根据二级索引的主键ID进行回表操作,性能上比索引是主键要慢。

2.3 Block Nested-Loop Join(减少内层表数据的循环次数)

缓存块嵌套循环连接通过一次性缓存多条数据,把参与查询的列缓存到Join Buffer 里,然后拿join buffer里的数据批量与内层表的数据进行匹配,从而减少了内层循环的次数(遍历一次内层表就可以批量匹配一次Join Buffer里面的外层表数据)。

当不使用Index Nested-Loop Join的时候(内层表查询不适用索引),默认使用Block Nested-Loop Join

  1. Join Buffer会缓存所有参与查询的列而不是只有Join的列
  2. 可以通过调整join_buffer_size缓存大小
  3. join_buffer_size的默认值是256K,join_buffer_size的最大值在MySQL 5.1.22版本前是4G-1,而之后的版本才能在64位操作系统下申请大于4G的Join Buffer空间
  4. 使用Block Nested-Loop Join算法需要开启优化器管理配置的optimizer_switch的设置block_nested_loop为on,默认为开启

三 优化

  1. 用小结果集驱动大结果集,减少外层循环的数据量:如果小结果集和大结果集连接的列都是索引列,mysql在内连接时也会选择用小结果集驱动大结果集,因为索引查询的成本是比较固定的,这时候外层的循环越少,join的速度便越快
  2. 为匹配的条件增加索引:争取使用INLJ,减少内层表的循环次数
  3. 增大join buffer size的大小:当使用BNLJ时,一次缓存的数据越多,那么外层表循环的次数就越少
  4. 减少不必要的字段查询:
    • 当用到BNLJ时,字段越少,join buffer 所缓存的数据就越多,外层表的循环次数就越少
    • 当用到INLJ时,如果可以不回表查询,即利用到覆盖索引,则可能可以提示速度
  5. 尽量使用inner join,避免left join 和NULL

摘抄自(有删改):https://blog.csdn.net/agonie201218/article/details/106993948

四 补充

4.1 找出所有在左表,不在右表的纪录

注:列值为null应该用is null 而不能用=NULL

  a.user_id 列必须声明为 NOT NULL 的

select id, name, action from user as u left join user_action a on u.id = a.user_id where a.user_id is NULL

4.2 where使用

在连表查询时,通常在子查询中使用 WHERE 子句限制表数据会比在最后的主查询中使用 WHERE 子句效率更高

原因是,在子查询中使用 WHERE 子句可以对较小的结果集进行过滤,减少了主查询需要处理的数据量。这样可以减少数据的传输和处理的负担,提高查询性能。

另一方面,在最后的主查询中使用 WHERE 子句时,会先执行联接操作并获取所有的匹配行,然后再对整个结果集进行过滤。这样会导致在查询过程中处理了更多的数据,增加了查询的开销,可能导致性能下降。

因此,将限制条件放在子查询中,可以尽早地过滤数据,只将需要的数据传递到后续的查询阶段,减少了不必要的计算和数据传输,更加高效。

SELECT A.*
FROM 大表A A
JOIN (SELECT * FROM 小表B WHERE C) AS B ON A.关联键 = B.关联键;

4.2 多表联合查询

在MySQL关联查询中,建议将小表作为驱动表,而将大表作为被驱动表

因为小表通常拥有较少的记录,而大表可能包含大量的数据。当小表作为驱动表时,MySQL可以先从小表中获取数据,并使用这些数据来查询大表。这样做的好处是可以减少查询的数据量,提高查询的效率。如果将大表作为驱动表,MySQL需要先扫描大表的所有记录,然后再根据关联条件查询小表,这样会增加查询的时间和资源消耗。

需要注意的是,选择驱动表的原则是根据查询的条件和数据量来决定,而不是根据表的大小。有时候大表可能也是更适合作为驱动表的,这需要根据具体的情况进行分析和测试。

假设t4为大表:

select
b.name,
c.view_name,
a.notify_time,
a.product,
a.alarm_id
from
(
select
psa,
group_id
from
t1
) a
left join (
select
id,
name
from
t2
) b on a.group_id=b.id
left join (
select
view_name,
psas
from
t3
where
type='alarm'
) c on concat('"', c.psas, '"') regexp a.psa
left join (
select
notify_time,
product,
alarm_id
from
t4
where
product!='/'
) d on d.product=b.psa

Mysql--JOIN连表查询的更多相关文章

  1. MySQL之多表查询一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习

    MySQL之多表查询 阅读目录 一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习 一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 首先说一下,我们写项目一般都会建 ...

  2. day15(mysql 的多表查询,事务)

    mysql之多表查询 1.合并结果集 作用:合并结果集就是把两个select语句查询的结果连接到一起! /*创建表t1*/ CREATE TABLE t1( a INT PRIMARY KEY , b ...

  3. mysql数据库优化课程---11、mysql普通多表查询

    mysql数据库优化课程---11.mysql普通多表查询 一.总结 一句话总结:select user.username,user.age,class.name,class.ctime from u ...

  4. Mariadb/MySQL数据库单表查询基本操作及DML语句

    Mariadb/MySQL数据库单表查询基本操作及DML语句 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一数据库及表相关概述 1>.数据库操作 创建数据库: CREATE ...

  5. day 39 MySQL之多表查询

    MySQL之多表查询   阅读目录 一 介绍 二 多表连接查询 三 符合条件连接查询 四 子查询 五 综合练习 一 介绍 本节主题 多表连接查询 复合条件连接查询 子查询 首先说一下,我们写项目一般都 ...

  6. MySQL的联表查询

    MySQL的联表查询 首选:分析查询的字段来自哪些表 进而:确定交集 然后:确定判断的条件 比如:从student表 和 result表 查学号.考试名称.学时.考试日期.考试成绩 表1: 学号 考试 ...

  7. 对于大量left join 的表查询,可以在关键的 连接节点字段上创建索引。

    对于大量left join 的表查询,可以在关键的 连接节点字段上创建索引. 问题: 大量的left join 怎么优化 select a.id,a.num,b.num,b.pcs,c.num, c. ...

  8. Vc数据库编程基础MySql数据库的表查询功能

    Vc数据库编程基础MySql数据库的表查询功能 一丶简介 不管是任何数据库.都会有查询功能.而且是很重要的功能.上一讲知识简单的讲解了表的查询所有. 那么这次我们需要掌握的则是. 1.使用select ...

  9. mybatis逆向工程,实现join多表查询,避免多表相同字段名的陷阱

    ​ mybatis逆向工程,实现join多表查询,避免多表相同字段名的陷阱 ​ 前言:使用 mybatis generator 生成表格对应的pojo.dao.mapper,以及对应的example的 ...

  10. MySQL之单表查询 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER BY 八 限制查询的记录数:LIMIT 九 使用正则表达式查询

    MySQL之单表查询 阅读目录 一 单表查询的语法 二 关键字的执行优先级(重点) 三 简单查询 四 WHERE约束 五 分组查询:GROUP BY 六 HAVING过滤 七 查询排序:ORDER B ...

随机推荐

  1. windows10 使用 USB 无线网卡的热点功能

    一.概述 在某宝上买了一个 COMFAST CF-727B 的无线模块,由于笔记本电脑一直使用不上,所以放了很久.多年后我来到了一个公司,遇到了我此生最想吐槽的网管,简直不敢想象几十人的办公室,居然能 ...

  2. 写代码不用"if"行不行,曾经的反 if 运动

    如果在IT行业的时间够长的话,可能还记得大约10几年前,设计模式风靡一时的时候,有过一段反 "if" 的运动. 所谓的反"if"运动,其实是夸大了"i ...

  3. weblogic端口号和内存怎么修改?

    在WebLogic中修改端口号和内存分配是一项重要的任务,它涉及到服务器性能和应用程序的可靠性.下面我将详细介绍如何修改WebLogic的端口号和内存设置. 修改端口号 WebLogic使用多个端口来 ...

  4. 基于DotNetty实现自动发布 - 项目的配置与发现

    前言 上一篇,我们实现了基于 DotNetty 的通信基础模块的搭建,本篇,主要实现待发布 Web 项目的集成. 创建待发布项目 为了测试, 我创建了一个基于 .NET 4.8 的 Web 项目 Op ...

  5. DFT与ATE IP TEST

    IP的DFT设计测试与ATE IP TEST是一个设计,测试活动吗? 不是. 这两个设计对于前端工农村很容易搞混,认为是同一个人负责,同一个活动.实际情不是. DFT主要空DSC控制器对IP进行扫描, ...

  6. [ABC318G] Typical Path Problem

    Problem Statement You are given a simple connected undirected graph $G$ with $N$ vertices and $M$ ed ...

  7. [ABC263E] Sugoroku 3

    Problem Statement There are $N$ squares called Square $1$ though Square $N$. You start on Square $1$ ...

  8. .NET8 AOT和JIT的性能,谁更高呢?

    一: 有人问:.NET8 AOT和JIT的性能,谁更高呢? 原文:.NET8 AOT和JIT的性能,谁更高呢? 其实这个答案非常明显,那就是JIT的性能更高.为什么?原因在哪?因为JIT是随时可能分层 ...

  9. 零基础 从 yolo8 入门计算机视觉超简单:物体识别、图像分类、轨迹追踪、姿势识别

    目录 安装 Ultralytics 训练 模型验证 预测 & 识别 导出 追踪 图像分割提取 分类 姿势识别 轨迹生成 Ultralytics YOLOv8 是备受好评的实时目标检测和图像分割 ...

  10. MySQL调优的一些总结

    SQL优化可以从那几个方面去优化 1.基本写法优化: 1.少使用select * ,尽量使用具体字段: 2.对于条件来说等号之类两边的字段类型要一致,字符串不加单引号索引会失效: 3.尽量少使用Ord ...