MySQL表连接

989 阅读5分钟

「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

作为coder,工作中总是离不开数据库,数据库最绕不开的就是MySQL数据库。

MySQL开源好用、性能足、易扩展,可以说是项目开发必不可少的利器,但是对于稍微复杂一点的业务逻辑,总是少不了表的联合查询,今天就来学习MySQL中的表连接。

1. MySQL的表连接方式

常用的表连接方式有内连接和外连接,具体连接方式有:

  • join:inner join的简写
  • inner join:取关联表的交集
  • left join:以左表为主,结果为两表交集+左表的剩余数据,可以使用where条件过滤左表独有数据
  • right join:以右表为主,结果为两表交集+右表的剩余数据,可以使用where条件过滤右表独有数据

2. JOIN

join,即 inner join,mysql内连接的inner是可以省略的。如果不知道inner可以省略,第一次碰到join连接时确实会不断寻找inner/left/right等关键字,与此相同的是,left join和right join就是left/right outer join的简写。 尽管简写更简洁方便,但是对于inner join,建议还是完整使用,因为这样更容易看出使用的连接方式,而left/right join的简写不会影响直观性。

3. INNER JOIN

inner join,即表的内连接,是根据连接条件,获取两个表的数据交集。

3.1 inner join内连接流程

  1. 首先确定驱动表和被驱动表,mysql会根据内部机制判定关联表更小的作为驱动表,并不是按照sql的书写顺序,可以使用explain命令查看sql执行计划中的表顺序,
  2. 内连接联合查询时,依次取出驱动表的一条数据,然后根据连接条件遍历被驱动表中的所有数据,
    • 如果被驱动表中有数据满足连接条件,则取出当前数据作为结果表的一条数据;
    • 如果遍历完被驱动表没有找到满足连接条件的数据,则抛弃当前驱动表的数据,开始下一条数据
  3. 循环遍历驱动表中的所有数据,得到最终联合查询结果集。

3.2 inner join使用注意

对于inner join内连接,mysql会根据实际情况选择较小的表来驱动更大的数据表,此处的小表不只是对应表的大小,而是在执行相关过滤条件后的结果集表。

因此,为了进一步提升inner join联合查询语句的性能,我们可以利用MySQL的驱动机制:

  1. 被驱动表关联字段使用索引:驱动表是小表且一定会遍历所有数据,因此即使有索引,也不会有明显性能提升,而在被驱动表的连接条件字段建立索引会在搜索数据时使用索引,性能提升比较明显。
  2. 如果有where过滤条件,可以考虑对连接条件和过滤条件创建复合索引
  3. 如果联合查询中使用了group by或者order by等排序条件
    • 如果是应用在驱动表上,则将分组/排序条件在where条件之后建立联合索引
    • 如果是应用在被驱动表上,则应该尽量让其作为驱动表,

4. LEFT JOIN

left join,即左连接,是以左表为主进行的联合查询,最终结果是两表取交集(满足连接条件的结果)再加上左表独有的数据(右表无数据,设置为null)。

4.1 left join联合查询流程

  1. 左连接强制指定以左表为驱动表,右表为被驱动表,无论两者数据集的大小
  2. 从左表中按照顺序取出数据,针对当前数据遍历右表判断是否满足连接条件
    • 如果找到满足条件的数据,则将该数据放入结果表中;
    • 如果没有满足条件的数据,则把右表该行对应的字段赋值为null,并将左表的当前数据放入结果中;
  3. 选择下一条左表中的数据,继续进行步骤3,直到左表遍历完成后返回结果表。

4.2 left join关联优化

  • 在使用left join联合查询时,会固定使用左表作为驱动表,右表作为被驱动表,此时可以类比于inner join中的驱动表和被驱动表进行索引优化
  • 当外连接中使用了where过滤条件,且条件字段属于被驱动表中的字段,此时说明被驱动表的数据一定不为null,相当于取左右两表交集,MySQL会将left join外连接动转为inner join内连接

5. RIGHT JOIN

right join,右表连接,是以右表为主进行的联合查询,右表作为驱动表,左表作为被驱动表。

如果将右表连接中的表顺序交换,并将right join换为left join,则是相同的执行效果。实际上,mysql在执行右表连接查询时,就是将其转换成左表连接查询进行的。因此right join在实际执行中的流程和相关优化方式和left join一致。