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

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

相关推荐
androidwork43 分钟前
Android LinearLayout、FrameLayout、RelativeLayout、ConstraintLayout大混战
android·java·kotlin·androidx
每次的天空1 小时前
Android第十三次面试总结基础
android·面试·职场和发展
pp-周子晗(努力赶上课程进度版)1 小时前
【MySQL】视图、用户管理、MySQL使用C\C++连接
数据库·mysql
wu_android1 小时前
Android 相对布局管理器(RelativeLayout)
android
超级小忍2 小时前
如何配置 MySQL 允许远程连接
数据库·mysql·adb
吹牛不交税2 小时前
sqlsugar WhereIF条件的大于等于和等于查出来的坑
数据库·mysql
李斯维3 小时前
循序渐进 Android Binder(二):传递自定义对象和 AIDL 回调
android·java·android studio
androidwork3 小时前
OkHttp 3.0源码解析:从设计理念到核心实现
android·java·okhttp·kotlin
Java水解3 小时前
MySQL DQL全面解析:从入门到精通
后端·mysql