【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、总结

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

相关推荐
程序员小八7773 小时前
MySQL 事务:一文把 ACID、隔离级别、MVCC、锁全串起来
数据库·mysql
又见情义5 小时前
RK3568 Android 13 板载驱动适配-USB
android·arm开发·驱动开发
delta_hell5 小时前
【阅读源码-Android】动画之Choreographer-2
android·源码·choreographer
mmsx6 小时前
基于 Android 的博物馆文化展示与预约 App —— 设计与实现(有源码和文档)
android·app·源码·文档
一笑的小酒馆6 小时前
AndroidAGP9.0升级之路
android
阮胜昌7 小时前
MySQL 中的动态数据脱敏:无需更改应用程序即可保护敏感数据
android·mysql·adb
小白说大模型8 小时前
AI驱动的个性化学习路径:知识图谱与知识点关联的存储与推理
大数据·人工智能·学习·mysql·机器学习·prompt·知识图谱
这个DBA有点耶9 小时前
多模数据库深度解读:从“多库拼装”到“一库多能”的架构演进
数据库·mysql·dba
aaajj9 小时前
关于MODIFY_PHONE_STATE权限
android
程序员夏洛9 小时前
MySQL 默认的事务隔离级别是什么?为什么选择这个级别?
数据库·mysql