对于in子查询性能,众说纷纭。有的人说 in 子查询性能很差,不能使用索引。而有人说 in 子查询能用索引,而且性能很好。
今天我就给大家做个实验,来验证这些说法。
首先,我使用MySQL_5.1.73做测试。
有一个test库,库中有两张表:
data_school:全国各地的学校
t1 :三个学校id
我们来演示两种in子查询:
第一种:直接输入具体的值:
select * from data_school where id in (1101010002,1101010012,1101010014);
select * from data_school where id in ( select id from t1 );
大家可以看到,两者的性能都不在一个数量级上,非常的夸张。
我们再用explain去分析它们使用索引的情况。
对于explain与 profiling如果还不了解的话,可以看我上一篇文章。
对于第一条语句,大家可以看到,是一个simple 查询,没有子查询,而且使用了primary key索引。
我们再看看第二条语句:
首先是对data_school做了全盘扫描,这个是比较失败的查询。
这条查询和我们的思维不太一样,我们一般会认为
先执行 select id from t1,
再执行select * from data_school。
而实际的情况是,select * from data_school做全盘扫描,然后再一条条的去匹配表t1。
现在大家明白了吧,遇到这种问题,不能按我们的直觉去判断,要通过具体的实验分析获取结果。
最后注意一点
MySQL升级到5.6的时候,这个问题已经被修复,我再给大家看一个在MySQL5.6中的实验。直接上图:
大家可以看到没啥大的差距。
看下图,大家注意到没有,相比5.1.37,它们查询的顺序发生了变化,先查t1,使用primary key。
然后再查data_school,也使用了primary key。两条查询都是simple类型。
MySQL5.6修复了这个问题,这大概就是为什么有人说性能差,有人说性能好的原因吧!
建议大家使用较高版本的MySQL。