mysql笔记 表连接

110 阅读4分钟

join的基本使用

在mysql的使用中我们可能需要将两张表的数据做关联合并成一条数据返回,这就需要我们使用join语句来连接我们想要连接的表。

连接的本质就是将参与到连接的表的数据取出来,依次匹配组合,再将结果返回给用户。

image.png 查询的结果包含了一个表的每一条数据和另一张表的所有数据匹配的组合,这样的结果被称为笛卡尔积。

如果要关联的表多了,那么就是拿前一次的结果集和下一张表的数据做上述操作。

数据量少还好,但如果我们不做限制并且关联的表的数据有一点点多的话得到的笛卡尔积就会非常庞大了。

为了限制数量,我们最好在查询的时候加上过滤条件。比如T1.age > 10, T2.name like '小%' ,T1.userId = T2.userId等。

第一个查询的表可以称为驱动表,按照筛选条件筛选出符合条件的数据出来。

第二张表可以称为被驱动表,因为第二张表是根据第一张表的结果来做匹配的。在驱动表数据和被驱动表数据进行关联的时候如果有相关的被驱动表的筛选条件也会进行筛选,最后将匹配的数据与驱动表提供的数据做关联。

驱动表提供的数据是一条条进行匹配关联的。

内连接、外连接

连接分为内连接和外连接,两者的区别就在于内连接不会保留驱动表未匹配的记录到结果集中而外连接会。

比如我的User1表有UserId这个字段,从1到10,User2表有userId和sex这两个字段,有5条数据,serId分别从1到5。我们使用内连接进行查询,查询出的结果只会有1到5,不会有6到10。而如果我们使用外连接就能在结果中查询到6到10的数据,只不过相关的sex字段为空。

外连接又可以分为左外连接和右外连接,分别以左和右作为驱动表。

在实际的使用中为了区分好我们实际就不想要的数据和即使没匹配上也要留下的数据。我们会使用on和where分别进行筛选条件的编写。

不符合where子句中的过滤条件不会显示在结果中,不符合on子句中的筛选条件在外连接的情况下会保留在结果集中,没有的字段就用null代替,在内连接中on子句和where子句等效。

连接的原理

嵌套循环连接

连接的过程可以大体如下:先对驱动表进行一次访问查询,查询出符合条件的数据,这些数据每个都要单独访问被驱动表做匹配。如果有多个表,那么前两个表的结果的每条数据又会和后面的一张表的数据依次做匹配,整体的形式就是循环嵌套起来的。

优化

在使用时驱动表只会被访问一次,而被驱动表则会被访问多次,但终究是对表的访问,只要我们的索引和查询条件设置的合理,在查询的时候就会通过索引来提升我们的查询速度。

但如果条件不合适(比如没用索引、被驱动表数据量过大,无法全部暂存到内存等情况),那么对被驱动表的访问就会产生大量的IO,磁盘的IO对于CPU来说十分缓慢,比如说被驱动表的数据需要3张内存页存储,那么一条数据和被驱动表的数据做对比可能就会有3次IO。

所以为了提升效率设计出了join buffer。join buffer是一块内存空间,它会存储驱动表查询出来的数据,在使用时会先把若干条驱动表数据放到这里,再将这些数据和被驱动表的数据做匹配,这就使得在做匹配时被驱动表的一条数据可以和多条驱动表数据对比匹配提升效率,从而减少IO次数。