多表查询
连接的过程
- 首选确定第一个需要查询的表,这个表被称为
驱动表
(基于单表查询代价最小的表)。根据条件过滤驱动表数据。驱动表只会被查询一次。 - 根据驱动表查询的每一条记录依次去
被驱动表
中寻找匹配的记录。驱动表有多少条符合条件的数据,被驱动表就会被访问几次。
连接的类型
sql
# 内连接
SELECT A.*, B.* FROM A,B WHERE A.id = B.id;
# 左外连接
SELECT A.*, B.* FROM A LEFT JOIN B ON A.id = B.id WHERE A.age > 10;
# 右外连接
SELECT A.*, B.* FROM A RIGHT JOIN B ON A.id = B.id WHERE A.age > 10;
如果是超过两张表的连接,那么先连接两张表,再将两张表的结果作为新的驱动表执行连接操作。
连接的原理
循环嵌套连接
驱动表只访问一次,但被驱动表却可能被多次访问,访问次数取决于对驱动表执行单表查询后的结果集中的记录条数
的连接执行方式称之为嵌套循环连接
(Nested-Loop Join
)
- 步骤1:选取驱动表,使用与驱动表相关的过滤条件,选取代价最低的单表访问方法来执行对驱动表的单表查询。
- 步骤2:对上一步骤中查询驱动表得到的结果集中每一条记录,都分别到被驱动表中查找匹配的记录。
我们可以通过给被驱动表添加
索引
来实现快速连接,因为被驱动表可能会访问多次。
基于块的连接
循环嵌套连接中,每次匹配都是驱动表
拿出一条记录,然后从被驱动表中取出记录加载到内存中
,然后被驱动表的记录和这一条驱动表记录进行比对,然后从内存中清除被驱动表记录。再拿出驱动表的另一条记录,再将被驱动表的记录加载到内存中进行比对,所以有多少条驱动表记录,那么被驱动表就会被加载到内存中多少次。
块连接是基于join buffer
的嵌套连接算法。
join buffer
是在执行连接查询前申请的一块固定大小的内存
,先把若干条驱动表结果集中的记录装在这个join buffer
中,然后开始扫描被驱动表,每一条被驱动表的记录一次性和join buffer
中的多条驱动表记录做匹配。
假设A表和B表进行基于块的连接查询,那么A表会根据A的条件进行单表查询(不包含关联条件),将结果放入join buffer
,再执行B表的条件查询(不包含关联条件),将结果放入join buffer
中,在内存中进行匹配,执行一批后再进行下一批,如此往复。
join buffer
通过参数join_buffer_size
设置,默认262144字节(256k)
。需要注意的是驱动表的记录并不是所有列
都会被放到join buffer
中,只有查询列表中的列和过滤条件中的列
才会被放到join buffer
中,所以连接查询中我们不要用*
作为查询列,这样可以将更多的表记录放到join buffer
中。