证明Join语句小表作为驱动表更好

51 阅读2分钟

假设dept表10条数据,user表1000条数据:

select user.name,user.age,dept.name,dept.desc from dept left join user on dept.name = user.name

这条语句的意思是获取dept表的所有记录,然后根据on条件一条一条去user表中查询,如果有相同的name就组合起来,如果没有就用null代替。 驱动表是dept表(主动发起查询的表),被驱动表是user表(是根据on条件被查询的表)。

分类讨论:
1.user表上没有name字段的索引
一般思路:
从dept中读入一条数据,取出name字段到表user中全表查询,取得对应主键,
根据主键回表查询,取出数据然后组合,然后从dept读入第二条数据,重复进行下去。
总共扫描10*1000=一万次。
mysql思路:
在内存中分配一个join_buffer,把dept数据全部读入线程内存join_buffer中,
从dept第一条数据开始,读入user表第一条数据对比是否满足on条件,满足就组合,
然后读入第二条数据对比,重复进行下去。
总共扫描10*1000=一万次,但是由于是在内存中操作,速度就快一点。
如果user表数据比较少就会一次读入join_buffer,如果比较大就会分多次读入join_buffer,因此小表作为驱动表更好。
2.user表上有name字段的索引
从dept中读入一条数据,取出name字段到表user的name索引树上去找到对应的主键,
根据主键回表查询,取出数据然后组合,然后从dept读入第二条数据,重复进行下去。
总共扫描100+100=200行,时间复杂度是o(dept行数)+o(dept行数*log(user表行数)*2),
可以看出dept行数比user表行数影响大,小表当驱动表更好。

综上所述,Join语句小表作为驱动表更好。

Join语句优化:
1.小表做驱动表
2.给被驱动表的join字段加上索引
3.如果使用频率低不便加上索引,给被驱动表创建临时表,给临时表的join字段加上索引