【MySQL】表连接原理

目录

1、背景

在进行sql查询时有时需要多张表的查询结果组成一个共同的结果返回,这时就用到了mysql中连接的用法,接下来就以两张表来讲解表连接的原理。

2、环境

创建两张表并插入数据如下:

sql 复制代码
mysql> select * from testjoin1;
+----+------+------+
| id | str1 | num1 |
+----+------+------+
|  1 | aaa  |  111 |
|  2 | bbb  |  222 |
|  3 | ccc  |  333 |
+----+------+------+
3 rows in set (0.00 sec)

mysql> select * from testjoin2;
+----+------+------+
| id | str2 | num2 |
+----+------+------+
|  1 | bbb  |  333 |
|  2 | ccc  |  444 |
|  3 | ddd  |  555 |
+----+------+------+
3 rows in set (0.00 sec)

3、表连接原理

【1】驱动表和被驱动表

两张表连接查询过程为:

1、先确定第一张要查询的表得到第一张表的查询结果,

2、第一张表的查询结果作为第二张表的查询条件进行查询得到最终查询结果。

其中第一张表叫驱动表 ,第二张表叫被驱动表,先看一下最基本连接查询的例子:

sql 复制代码
mysql> select * from testjoin1, testjoin2;
+----+------+------+----+------+------+
| id | str1 | num1 | id | str2 | num2 |
+----+------+------+----+------+------+
|  3 | ccc  |  333 |  1 | bbb  |  333 |
|  2 | bbb  |  222 |  1 | bbb  |  333 |
|  1 | aaa  |  111 |  1 | bbb  |  333 |
|  3 | ccc  |  333 |  2 | ccc  |  444 |
|  2 | bbb  |  222 |  2 | ccc  |  444 |
|  1 | aaa  |  111 |  2 | ccc  |  444 |
|  3 | ccc  |  333 |  3 | ddd  |  555 |
|  2 | bbb  |  222 |  3 | ddd  |  555 |
|  1 | aaa  |  111 |  3 | ddd  |  555 |
+----+------+------+----+------+------+
9 rows in set (0.00 sec)

再看一下执行计划:

sql 复制代码
mysql> explain select * from testjoin1, testjoin2;
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+----------------
---------------+
| id | select_type | table     | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra
               |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+----------------
---------------+
|  1 | SIMPLE      | testjoin1 | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL
               |
|  1 | SIMPLE      | testjoin2 | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | Using join buff
er (hash join) |
+----+-------------+-----------+------------+------+---------------+------+---------+------+------+----------+----------------
---------------+
2 rows in set, 1 warning (0.00 sec)

可以看到执行计划输出了两条,第一条代表testjoin1表是驱动表 , testjoin2表是被驱动表

【2】内连接

驱动表的查询结果作为查询条件但没有在被驱动表中匹配到结果时,这条记录就不会加入到最终结果集中,这种连接方式就叫内连接,例如:

sql 复制代码
mysql> select * from testjoin1 inner join testjoin2 on str1=str2;
+----+------+------+----+------+------+
| id | str1 | num1 | id | str2 | num2 |
+----+------+------+----+------+------+
|  2 | bbb  |  222 |  1 | bbb  |  333 |
|  3 | ccc  |  333 |  2 | ccc  |  444 |
+----+------+------+----+------+------+
2 rows in set (0.00 sec)

可以看到testjoin1表中str1为aaa的记录就不在查询结果中,用图红色部分表示:

【3】外连接

与内连接相对应的就是外连接,外连接中驱动表的查询结果作为查询条件即使没有在被驱动表中查到,也会展示在最终结果集中,外连接分为左外连接和右外连接,左外连接就是将左边的表作为驱动表,左外连接查询如下:

sql 复制代码
mysql> select * from testjoin1 left join testjoin2 on str1=str2;
+----+------+------+------+------+------+
| id | str1 | num1 | id   | str2 | num2 |
+----+------+------+------+------+------+
|  1 | aaa  |  111 | NULL | NULL | NULL |
|  2 | bbb  |  222 |    1 | bbb  |  333 |
|  3 | ccc  |  333 |    2 | ccc  |  444 |
+----+------+------+------+------+------+
3 rows in set (0.00 sec)

用图紫色部分表示:

右外连接就是将右边的表作为驱动表,右外连接查询如下:

sql 复制代码
mysql> select * from testjoin1 right join testjoin2 on str1=str2;
+------+------+------+----+------+------+
| id   | str1 | num1 | id | str2 | num2 |
+------+------+------+----+------+------+
|    2 | bbb  |  222 |  1 | bbb  |  333 |
|    3 | ccc  |  333 |  2 | ccc  |  444 |
| NULL | NULL | NULL |  3 | ddd  |  555 |
+------+------+------+----+------+------+
3 rows in set (0.00 sec)

用图绿色部分表示:

【4】嵌套循环连接

驱动表只会被访问一次,被驱动表可能被访问多次,取决于从驱动表中得到的结果,这种连接执行方式就叫嵌套循环连接

【5】join buffer

mysql中的查表过程就是把数据从磁盘中加载到内存进行比较查询,加载后面的记录时会释放内存中前面已经使用过的记录,我们上面说过被驱动表 可能会被访问很多次,每次都从磁盘重新加载数据到内存无疑会增加开销,所以提出了join buffer ,也就是存储驱动表 的所有查询结过,然后只执行一次将被驱动表 从磁盘加载到内存中,在内存中计算得到最终查询结果,前面测试连接的explain语句中就可以看到被驱动表的Extra字段中有Using join buffer。

4、总结

对驱动表进行查询时就相当于单表查询,也可以通过索引去优化查询速度,当确定了驱动表的查询结果时,其实被驱动的查询条件也就确定了,也可以通过加索引去优化查询速度,当然索引是否生效还要看和全表扫描的执行效率进行对比。

相关推荐
砖厂小工4 小时前
用 GLM + OpenClaw 打造你的 AI PR Review Agent — 让龙虾帮你审代码
android·github
张拭心5 小时前
春节后,有些公司明确要求 AI 经验了
android·前端·人工智能
张拭心5 小时前
Android 17 来了!新特性介绍与适配建议
android·前端
Kapaseker7 小时前
Compose 进阶—巧用 GraphicsLayer
android·kotlin
黄林晴7 小时前
Android17 为什么重写 MessageQueue
android
阿巴斯甜1 天前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker1 天前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq95271 天前
Andorid Google 登录接入文档
android
黄林晴1 天前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab2 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读