下载APP
关闭
讲堂
客户端下载
兑换中心
企业版
渠道合作
推荐作者

44 | 答疑文章(三):说一说这些好问题

2019-02-22 林晓斌
MySQL实战45讲
进入课程

讲述:林晓斌

时长16:20大小14.98M

这是我们专栏的最后一篇答疑文章,今天我们来说说一些好问题。

在我看来,能够帮我们扩展一个逻辑的边界的问题,就是好问题。因为通过解决这样的问题,能够加深我们对这个逻辑的理解,或者帮我们关联到另外一个知识点,进而可以帮助我们建立起自己的知识网络。

在工作中会问好问题,是一个很重要的能力。

经过这段时间的学习,从评论区的问题我可以感觉出来,紧跟课程学习的同学,对 SQL 语句执行性能的感觉越来越好了,提出的问题也越来越细致和精准了。

接下来,我们就一起看看同学们在评论区提到的这些好问题。在和你一起分析这些问题的时候,我会指出它们具体是在哪篇文章出现的。同时,在回答这些问题的过程中,我会假设你已经掌握了这篇文章涉及的知识。当然,如果你印象模糊了,也可以跳回文章再复习一次。

join 的写法

在第 35 篇文章《join 语句怎么优化?》中,我在介绍 join 执行顺序的时候,用的都是 straight_join。@郭健 同学在文后提出了两个问题:

  1. 如果用 left join 的话,左边的表一定是驱动表吗?

  2. 如果两个表的 join 包含多个条件的等值匹配,是都要写到 on 里面呢,还是只把一个条件写到 on 里面,其他条件写到 where 部分?

为了同时回答这两个问题,我来构造两个表 a 和 b:

create table a(f1 int, f2 int, index(f1))engine=innodb;
create table b(f1 int, f2 int)engine=innodb;
insert into a values(1,1),(2,2),(3,3),(4,4),(5,5),(6,6);
insert into b values(3,3),(4,4),(5,5),(6,6),(7,7),(8,8);
复制代码

表 a 和 b 都有两个字段 f1 和 f2,不同的是表 a 的字段 f1 上有索引。然后,我往两个表中都插入了 6 条记录,其中在表 a 和 b 中同时存在的数据有 4 行。

@郭健 同学提到的第二个问题,其实就是下面这两种写法的区别:

select * from a left join b on(a.f1=b.f1) and (a.f2=b.f2); /*Q1*/
select * from a left join b on(a.f1=b.f1) where (a.f2=b.f2);/*Q2*/
复制代码

我把这两条语句分别记为 Q1 和 Q2。

首先,需要说明的是,这两个 left join 语句的语义逻辑并不相同。我们先来看一下它们的执行结果。

图 1 两个 join 的查询结果

可以看到:

  • 语句 Q1 返回的数据集是 6 行,表 a 中即使没有满足匹配条件的记录,查询结果中也会返回一行,并将表 b 的各个字段值填成 NULL。
  • 语句 Q2 返回的是 4 行。从逻辑上可以这么理解,最后的两行,由于表 b 中没有匹配的字段,结果集里面 b.f2 的值是空,不满足 where 部分的条件判断,因此不能作为结果集的一部分。

接下来,我们看看实际执行这两条语句时,MySQL 是怎么做的。

我们先一起看看语句 Q1 的 explain 结果: