表连接中的驱动表与被驱动表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了表连接中的驱动表与被驱动表相关的知识,希望对你有一定的参考价值。

参考技术A

mysql中的表连接分为三种

1. 左连接 left join
左连接以左表为基础,查询出左表所有数据并且去匹配右表的数据,如果右表没
有数据,则为空

2. 右连接 right join
右连接以右表为基础,查询出右表所有数据并且去匹配左表的数据,如果左表没
有数据,则为空

3. 内连接 inner join
内连接会把左右表匹配的数据查询出来,不存在的数据直接忽略

驱动表与被驱动表的概念
驱动表是表连接中的基础表,也就是通过驱动表的数据结果集作为循环基础数据,然后一条一条的通过这个结果集的数据作为过滤条件到被驱动表中查询数据,然后合并

驱动与被驱动
左连接中 左表是驱动表,右表是被驱动表
右连接中 右表是驱动表,左表是被驱动表
内连接中 表数据量较小的表会由mysql自动选择作为驱动表去驱动大表
有一个重点是,如果where条件存在的话 mysql会根据where实际条件进行驱动表的选择
sql优化中,一个比较重要的点就是要用小表驱动大表

原因
mysql表关联的算法,是通过驱动表去循环被驱动表,比如说,20w的大表和200条的小表,如果大表驱动,那么是20w条记录外循环,内循环200条去连接查找,需要通过20w次连接,如果小表驱动,那么是200条记录外循环,内循环20w条去连接查找,只需要通过200次连接就可以了,并且驱动表是不会使用索引的

了解MySQL联表查询中的驱动表,优化查询,以小表驱动大表

一、为什么要用小表驱动大表

1、驱动表的定义

当进行多表连接查询时, [驱动表] 的定义为:

1)指定了联接条件时,满足查询条件的记录行数少的表为[驱动表]

2)未指定联接条件时,行数少的表为[驱动表](Important!)

忠告:如果你搞不清楚该让谁做驱动表、谁 join 谁,请让 MySQL 运行时自行判断

既然“未指定联接条件时,行数少的表为[驱动表]”了,而且你也对自己写出的复杂的 Nested Loop Join 不太有把握(如下面的实例所示),就别指定谁 left/right join 谁了,请交给 MySQL优化器 运行时决定吧。

如果您对自己特别有信心


2、mysql关联查询的概念:

MySQL 表关联的算法是 Nest Loop Join,是通过驱动表的结果集作为循环基础数据,然后一条一条地通过该结果集中的数据作为过滤条件到下一个表中查询数据,然后合并结果。


例: user表10000条数据,class表20条数据

select * from user u left join class c u.userid=c.userid

这样则需要用user表循环10000次才能查询出来,而如果用class表驱动user表则只需要循环20次就能查询出来

例:

select * from class c left join user u c.userid=u.userid


小结果集驱动大结果集

de.cel 在2012年总结说,不管是你,还是 MySQL,优化的目标是尽可能减少JOIN中Nested Loop的循环次数。

以此保证:永远用小结果集驱动大结果集(Important)!


二、优化联表查询

优化第一步之:根据驱动表的字段排序


left join不变,干嘛要根据非驱动表的字段排序呢?我们前面说过“对驱动表可以直接排序,对非驱动表(的字段排序)需要对循环查询的合并结果(临时表)进行排序!”的。

explain

SELECT mb.id……

FROM mb LEFT JOIN mbei ON mb.id=mbei.mb_id INNER JOINu ON mb.uid=u.uid  

WHERE 1=1  

ORDER BY mb.id DESC

limit 0,10

也满足业务场景,做到了rows最小:


优化第二步:去除所有JOIN,让MySQL自行决定,explain第一张表就是驱动表,数据量比其它两张表都要小!

explain
SELECT mb.id……
FROM mb,mbei,u
WHERE
mb.id=mbei.mb_id
and mb.uid=u.user_id
order by mbei.apply_time desc
limit 0,10

立竿见影,驱动表一样是小表 mbei:

id select_type table   type    possible_keys      key          key_len  ref                rows    Extra
1 SIMPLE mbei ALL mb_id (NULL) (NULL) (NULL) 13388 Using filesort
1 SIMPLE mb eq_ref PRIMARY,userid PRIMARY 4 mbei.mb_id 1
1 SIMPLE u eq_ref PRIMARY PRIMARY 4 mb.uid 1 Using index


三、总结

1、不要过于相信你的运气!

2、不要相信你的开发环境里SQL的执行速度!

3、请拿起 explain 武器,如果你看到以下现象,请优化:

1)出现了Using temporary

2)rows过多,或者几乎是全表的记录数

3)key 是 (NULL)

4)possible_keys 出现过多(待选)索引















































以上是关于表连接中的驱动表与被驱动表的主要内容,如果未能解决你的问题,请参考以下文章

MySQL--什么情况下不建议使用join查询

MySQL--什么情况下不建议使用join查询

Oracle常见的Hint

了解MySQL联表查询中的驱动表,优化查询,以小表驱动大表

JDBC连接数据库驱动及URL对应表

mysql join 谁是驱动表