0
点赞
收藏
分享

微信扫一扫

MySQL是怎样运行的——第十一章

修炼之士 2022-02-12 阅读 131

这一章主要是讲连接。

11.1

连接的本质就是把两个表中满足条件的记录取出来进行匹配。

稍微具体一些呢?
比如我们有两个表,t1和t2。
在这里插入图片描述
在这里插入图片描述

连接过程

现在有这样一个sql语句:

select * from t1, t2 where t1.m1 > 1 and t1.m1 = t2.m2 and t2.n2 < 'd';

这很显然是个内连接查询。我们首先要确定第一个需要查询的表,这个表称为驱动表。(自然,剩下的表叫做被驱动表)
那这里假设是t1(实际上会在查询优化的过程中决定选择哪个表)。

之后,我们会把t1表中满足条件的记录都“取出来”(只是打个比方,不会实际的存盘什么的)。
然后对每个表里的记录,我们都要去全扫描一下t2。比如第一条记录的t1.m1=2,,则根据t1.m1 = t2.m2,可以把t2相关的条件变成

t2.m2=2 and t2.n2 < 'd';

这样单独查t2就可以了。如法炮制,我们一共需要查询1次t1表,两次t2表。
总结,在两表的连接查询中,驱动表只需要访问一次,被驱动表可能需要访问多次

(注意不是把t1中的所有记录取出来存到某个地方,而是t1查一条就去匹配一次t2)

内外连接

内连接:如果驱动表中的记录在被驱动表中找不到匹配的记录,则该记录不会进入到最终的结果集。
外连接:即使驱动表中的记录在被驱动表中没有匹配的记录,也仍然需要加入到结果集。

而有的时候,我们又希望做外连接,但又不希望所有的驱动表记录都被加入到结果集中。这时候需要我们通过on来过滤。

where子句:不符合where子句中过滤条件的记录都不会被加入到最后的结果集。
on子句:即使无法在被驱动表找到匹配的记录,也会把这个记录加入到结果集中。

对于外连接来说,必须用on来指定连接条件。

11.2

这一节讲连接的原理

嵌套循环连接

就是我们刚才说的,在驱动表里找一条记录,然后拿着这条记录去扫描被驱动表全表。就像for循环嵌套一样。

使用索引加速查询

在固定驱动表的记录查询被驱动表时,可以利用索引。
在连接查询中对被驱动表的主键或唯一非空二级索引进行等值查询时,询问方法叫做eq_ref(这里注意,ref是允许空值的,eq ref不允许,所以应该是const>eq_ref>ref)
当然,别的访问方法也都是可以正常起作用的。

基于块的嵌套循环连接

这里的意思是,我们把驱动表中的记录先全部或尽可能多的存在Join Buffer(一个缓冲区,专门存驱动表记录的,默认256kb)中,然后进行被驱动表的扫描时,每次拿被驱动表的一条记录去匹配多条驱动表记录
比如我们把所有驱动表记录都存在join buffer里,那就相当于被驱动表只需要全表扫描一次。如果join buffer中存了一半的驱动表记录,则被驱动表只需要访问两次。

很显然,这是比较方便的事。而在把驱动表的记录存到join buffer中时,不会存所有列,只会存查询条件中的列和过滤条件中的列,因此少写select *。

select *带来的损失至少有:

  • 不能覆盖索引,需要回表。
  • 不能有效利用join buffer。

(这也提醒我可以把自己的数据库修改一下支持这个)

举报

相关推荐

0 条评论