5.1 概念
驱动表在SQL语句执行的过程中,总是先读取。而被驱动表在SQL语句执行的过程中,总是后读取。
在驱动表数据读取后,放入到join_buffer(join查询的时候,会把驱动表中的数据全部查询出来放入到内存中,而这个内存就是:join buffer)后,再去读取被驱动表中的数据,来和驱动表中的数据进行匹配。如果匹配上则作为结果集返回,否则丢弃。
5.2 区分
可以使用explain命令查看一下SQL语句的执行计划。在输出的执行计划中,排在第一行的表是驱动表,排在第二行的表是被驱动表。
5.3 写驱动表和被驱动表
5.3.1 inner join 内连接
最后返回的数据行数是在inner join前后两张表中同时存在的数据行数。任何一条只存在于某一张表中的数据,都不会返回。
对于inner join而言,MySQL会选择小表作为驱动表,大表作为被驱动表。这里对于大小的判断,是指真正参与关联查询的数据量所占用的join_buffer的大小来区分的,而不是根据表中所有的数据行数来判断的。
两个表在进行关联查询的时候,是根据真正参与关联查询的数据行和列所占用的空间大小来确认谁作为驱动表谁作为被驱动表的。不能单独看表的数据总数据行数来决定谁是驱动表谁是被驱动表。要看实际参与关联的数据行是多少,还要看实际参与关联查询的字段有哪些,因为有些表虽然有很多的字段,但是我们关联查询的时候,实际上在select后面只用了1个字段,此时在计算参与关联查询的表锁占用的空间大小的时候,把这个表的所有字段都计算进来显示是不合理的。
只要是在where条件中出现的表,就是驱动表。显然通过我们上面的实验可以看出这个观点是不正确的。两条SQL语句,在where条件中都使用了a.id作为过滤条件,但是驱动表却因为过滤行数的不同而出现截然相反的结果。有些在where条件中没有出现的表,也可能是驱动表。
select a.*, b.code from A as a inner join B as b on a.id = b.id;
5.3.2 left join 左外连接
left左边的表为主表,left右边的表为从表。返回结果行数以left左边的表的行数为最后的数据行,对于左表中有些数据行在右表中找不到它所匹配的数据行记录时候,返回结果的时候这些行后面通常会以null来填充。
下面的SQL中,A是驱动表,B是被驱动表。left join的左表示驱动表,右表示被驱动表。
select * from A as a left join B as b on a.id = b.id;
5.3.3 right join 右外连接
right右边的表为主表,right坐标的表为从表。返回结果行数以right右边的表的行数为左后的数据行,对于主表中有些数据行在从表中找不到它所匹配的数据行记录时候,返回结果的时候这些行后面通常会以null来填充。
下面的SQL中,A是被驱动表,B是驱动表。right join的右表示驱动表,左表示被驱动表。
select * from A as a right join B as b on a.id = b.id;
5.3.4 full join 全外连接
FULL OUTER JOIN 关键字只要左表(table1)和右表(table2)其中一个表中存在匹配,则返回行。FULL OUTER JOIN 关键字结合了 LEFT JOIN 和 RIGHT JOIN 的结果。MySQL 数据库不支持全连接,想要实现全连接可以使用 UNION ALL 来将左连接和右连接结果组合在一起实现全连接。Oracle中有full join这种写法。
UNION :联合的意思,即把两次或多次查询结果合并起来
要求:两次查询的列数必须一致,同时,每条 SELECT 语句中的列的顺序必须相同
推荐:列的类型可以不一样,但推荐查询的每一列,相对于的类型应该一样
select c.name as course_name, t.name as teacher_name, t.country as teacher_countryfrom courses c left join teachers t on c.teacher_id = t.idunionselect c.name as course_name, t.name as teacher_name, t.country as teacher_countryfrom courses c right join teachers t on c.teacher_id = t.id
5.3.5 straight_join
straight_join的含义和上面的inner join有些类似,它也是对两个表进行inner join的操作,但是它属于一种特殊的inner join。
在关联查询的时候,inner join 会根据两个关联的表的大小自动的选择哪一个表作为驱动表,哪一个表作为被驱动表。这个由MySQL内部的优化器自己去选择的。但是MySQL的优化器也不是100%靠谱,有时候由于我们对表频繁的CURD操作,表的统计信息也可能不够准确,所以它也会选择错误的优化方案。比如选择了错误的表作为驱动表,这样将导致我们的查询效率变得很低。
straight_join 的功能是可以指定在 straight_join 前面的表作为驱动表,在 straight_joion 后面的表作为被驱动表。这样我们就可以指定让MySQL选择哪个表作为驱动表哪个表作为被驱动表了。
select * from A as a straight_join B as b on a.id = b.id;
