MySQL连接查询原理是什么?两大表怎么亲密接触?

文章导读
MySQL 连接查询的原理本质上是将多个表中的记录通过特定的连接条件进行匹配组合,形成一张更大的虚拟结果集。两大表“亲密接触”的过程通常涉及驱动表与被驱动表的选择,优化器会根据索引和数据量决定扫描顺序。连接方式包括内连接、外连接和交叉连接,其中内连接只保留匹配记录,外连接保留主表所有记录。为了避免笛卡尔积导致的性能问题,必须在连接时加上有效的过滤条件,利用索引减少扫描次数,从而实现高效的数据关联查
📋 目录
  1. A MySQL 数据库,深入了解连接查询及原理 (二)
  2. B 面试之前,MySQL 表连接必须过关!——表连接的原理
  3. C mysql 进阶优化篇 04——深入 JOIN 语句的底层原理
  4. D FAQ
A A

MySQL 连接查询的原理本质上是将多个表中的记录通过特定的连接条件进行匹配组合,形成一张更大的虚拟结果集。两大表“亲密接触”的过程通常涉及驱动表与被驱动表的选择,优化器会根据索引和数据量决定扫描顺序。连接方式包括内连接、外连接和交叉连接,其中内连接只保留匹配记录,外连接保留主表所有记录。为了避免笛卡尔积导致的性能问题,必须在连接时加上有效的过滤条件,利用索引减少扫描次数,从而实现高效的数据关联查询。

MySQL 数据库,深入了解连接查询及原理 (二)

外连接涉及到 2 个表,分为:主表和从表,要查询的信息主要来⾃于哪个表,谁就是主 表。外连接查询结果为主表中所有记录。如果从表中有和它匹配的,则显⽰匹配的值,这部分 相当于内连接查询出来的结果;如果从表中没有和它匹配的,则显⽰ null。最终:外连接查询结果 = 内连接的结果 + 主表中有的⽽内连接结果中没有的记录。外连接分为 2 种:左外链接:使⽤ left join 关键字,left join 左边的是主表。右外连接:使⽤ right join 关键字,right join 右边的是主表。语法 select 列 from 主表 left join 从表 on 连接条件; 示例 1: 查询所有员⼯信息,并显⽰员⼯所在组,如下:t1.emp_name, t2.team_name FROM t_employee t1 LEFT JOIN t_team t2 ON t1.team_id = t2.id; +---------------+-----------+ | emp_name | team_name | +---------------+-----------+ |路⼈甲 Java | 架构组 | | 张三 | 测试组 | | 李四 | java 组 | | 王五 | NULL | | 赵六 | NULL |+---------------+-----------+ 5 rows in set (0.00 sec) 上⾯查询出了所有员⼯,员⼯ teamid=0 的,teamname 为 NULL。示例 2: 查询员⼯姓名、组名,返回组名不为空的记录,如下:t1.emp_name, t2.team_name FROM t_employee t1 LEFT JOIN t_team t2 ON t1.team_id = t2.id WHERE t2.team_name IS NOT NULL; +---------------+-----------+ | emp_name | team_name | +---------------+-----------+ |路⼈甲 Java | 架构组 | | 张三 | 测试组 | | 李四 | java 组 | +---------------+-----------+ 3 rows in set (0.00 sec) 上⾯先使⽤内连接获取连接结果,然后再使⽤ where 对连接结果进⾏过滤。语法 select 列 from 从表 right join 主表 on 连接条件;示例 我们使⽤右连接来实现上⾯左连接实现的功能,如下:(截至 2025 年 3 月 24 日)

面试之前,MySQL 表连接必须过关!——表连接的原理

代码语言:javascript AI 代码解释 create tablet1(m1 int,n1char(1));create tablet2(m2 int,n2char(1));insert into t1values(1,'a'),(2,'b'),(3,'c');insert into t2values(2,'b'),(3,'c'),(4,'d'); t1 表数据如下 t2 表数据如下 我们知道,所谓表连接就是把各个表中的记录都取出来进行依次匹配,最后把匹配组合的记录一起发送给客户端。比如下面把 t1 表和 t2 表连接起来的过程如下图 什么是连接查询?比如上面 t1 和 t2 表的记录连接起来组成一个新的更大的记录,这个查询过程就称为连接查询。什么是笛卡尔积? 如果连接查询的结果集中包含一个表中的每一条记录与另一个表中的每一条记录相互匹配组合的记录,那么这样的结果集就可以称为笛卡尔积。代码语言:javascript AI 代码解释 # 这三者效果一样,只要不写条件,就产生笛卡尔积,结果集的数量一样。select*from t1,t2;# 内连接 select*from t1 inner join t2;# 全连接 select*from t1 cross join t2; 表 t1 中有 3 条记录,表 t2 中也有 3 条记录,两个表连接后的笛卡尔积就有 3 x 3 = 9 条记录,只要把两个表的记录数相乘,就能得到笛卡尔积的数量。 笛卡尔积也是一个很大的问题,不加限制条件,结果集的数量就会很大。比如你在开发过程中需要 2 个表的连接,表 1 有 20000 条记录,表 2 有 10000 条记录,表 3 有 100 条记录,那么 3 张表连接后产生的笛卡尔积就有 20000 x 10000 x 100 = 20000000000 条记录 (两百亿条记录)。 所以在连接时过滤掉特定的记录组合是很有必要的,为了避免笛卡尔积,一定要在表连接的时候加上条件! 下面来看一下有过滤条件的表连接的执行过程。代码语言:javascript AI 代码解释 # 下面两种写法都一样,执行效率没有区别,看看自己习惯于哪种写法 select*from t1 join t2 on t1.m1>1and t1.m1=t2.m2 and t2.n2<'d';select*from t1,t2 where t1.m1>1and t1.m1=t2.m2 and t2.n2<'d'; 注意:先说明条件的概念,要区分什么是连接条件和过滤条件!! 连接条件是针对两张表而言的,比如 t1.m1 = t2.m2、t1.n1 > t2.n2,表达式两边是两个表的字段比较。过滤条件是针对单表而言的,比如 t1.m1 > 1 是针对 t1 表的过滤条件,t2.n2 < 'd' 是针对 t2 表的过滤条件。1.首先确定第一个需要查询的表,这个表称之为驱动表。 在单表中选择代价最小的查询方式,简单理解就是走合适的索引即可。(2026 年 1 月 28 日的资料)

mysql 进阶优化篇 04——深入 JOIN 语句的底层原理

join 方式连接多表,本质就是各个表之间数据的循环匹配。MySQL5.5 版本之前,MySQL 只支持一种表间关联方式,就是嵌套循环。如果关联表的数据量很大,则 join 关联的执行时间会非常漫长。在 MySQL 5.5 以后的版本中,MySQL 通过引入 BNLJ 算法来优化嵌套执行。1.驱动表和被驱动表 驱动表就是主表,被驱动表就是从表、非驱动表。对于内连接来说:代码语言:javascript AI 代码解释 SELECT*FROMAJOINBONSQL 复制 A 并不一定就是驱动表,优化器会根据你的查询语句做优化,决定先查哪张表。先查询的表就是驱动表,反之就是被驱动表。通过 explain 关键字可以查看。该专栏的上一篇博客 Mysql 进阶优化篇 03——多表查询的优化已经总结了优化器选择的规律:两表中一个表有索引,一个表没有索引,则没有索引的为驱动表,有索引的为被驱动表;两个表都没有索引,则小表驱动大表。如果一个表有索引,但是数据量很小,一个表没有索引,但是数据量很大,情况会是怎样的呢?我们要明白优化器的优化原理:对于内连接 mysql 会选择扫描次数比较少的作为驱动表,因此实际生产中最好使用 Explain 测试验证。对于外连接来说:代码语言:javascript AI 代码解释 SELECT*FROMALEFTJOINBON 或 代码语言:javascript AI 代码解释 SELECT*FROMBRIGHTJOINAON 通常,大家会认为 A 就是驱动表,B 就是被驱动表。但也未必。测试如下:代码语言:javascript AI 代码解释 CREATETABLEa(f1INT,f2INT,INDEX(f1))ENGINE=INNODB;CREATEDTABLEb(f1INT,f2INT)ENGINE=INNODB;INSERTINTOavalues(1,1),(2,2),(3,3),(4,4),(5,5),(6,6);INSERTINTObvalues(3,3),(4,4),(5,5),(6,6),(7,7),(8,8); 代码语言:javascript AI 代码解释 EXPLAINSELECT*FROMaLEFTJOINbON(a.f1=b.f1)WHERE(a.f2=b.f2); 执行结果如下。明明我们写的是 a LEFT JOIN b,但是我们执行 sql 查询时,却是 b 作为了驱动表,a 作为了被驱动表。实际上,查询优化器会帮你把外连接改造为内连接,然后根据其优化策略选择驱动表与被驱动表。不信您可以执行下面 sql 对比验证。(该信息的时间戳是 2026 年 4 月 5 日)

FAQ

什么是笛卡尔积?

如果连接查询的结果集中包含一个表中的每一条记录与另一个表中的每一条记录相互匹配组合的记录,那么这样的结果集就可以称为笛卡尔积。

MySQL连接查询原理是什么?两大表怎么亲密接触?

驱动表是如何选择的?

优化器会根据查询语句做优化,决定先查哪张表。两表中一个表有索引,一个表没有索引,则没有索引的为驱动表,有索引的为被驱动表;两个表都没有索引,则小表驱动大表。

内连接和外连接有什么区别?

内连接只保留匹配的记录,外连接查询结果为主表中所有记录,如果从表中没有和它匹配的,则显示 null。