背景
探究使用exists或left join判断一条数据在另一个表中是否存在时,谁的效率更高。SQL语句如下:
select * from table1 where exists(select 1 from table2 where [table1.column]=[table2.column])
select * from table1 left join table2 on [table1.column]=[table2.column]
where [table2.column] is not null
对比过程
sqlserver中的效率对比
exists 执行时间:15秒
left join执行时间:27秒
根据下面两张图中的执行计划的结果来看,很明显,left join 比exists多执行一步,使用exists时,从头到尾扫描完索引进行条件检索,数据结果也就有了,而left join中,从头到尾扫描完索引检索后只是刚拿到left join 的结果,还没拿到最终结果,紧跟着还要执行联合查询,因为两个结果集inner join时没有索引,走的全表扫描,因此慢,比exists的方式多执行了12秒。
mysql中效率对比
exists 执行时间:13秒
left join执行时间:14秒
看如下两张执行计划图,与sqlserver一样,left join比exists多了一步。在exists中,利用a表的索引与b表的主键匹配迅速找出数据并判断条件是否符合,索引匹配完成,数据结果也就有了。但left join不一样,left join在exists的执行步骤的基础上,还做了一步inner join,本文例子中,mysql的left join只比exists多执行了1秒,是因为有索引,联合查询时利用了索引,上面的sqlserver在inner join时是没有索引的,因此sqlserver中的差距大,倒不是说sqlserver的效率本身低。
结论
关于使用exists或left join判断一条数据在另一个表中是否存在时,谁的效率更高的验证结论:
1、无论mysql还是sqlserver都是exists比left join效率高——因为exists一步完成,left join需要2步,而且第一步与exists一致,相当于多了一步。
2、没有索引的情况下,执行时间将近相差一倍——因为left join的第二步全表扫描耗时
3、有索引的情况下,差异不算太大——因为left join的第二步利用索引,相对耗时就少。
4、保持使用exists的习惯吧——毕竟从执行计划看,exists只走一步,left join走两步,而且第一步与exists一致