in 是把外表和内表作hash join,而exits是对外表作loop,每次loop再对内表进行查询。
如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in,
反之,如果外层的主查询记录较少,子查询中的表大且又有索引时应该用exists。
其实我们区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表作为驱 动表,先被访问;如果是in,那么以内层表作为驱动表,先被访问,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了,另外in时不对NULL进行处理。
如果查询的两个表大小相当,那么用in和exists差别不大。
如果两个表中一个较小,一个是大表,刚子查询表大的用exists,子查询表小的用in:
例如:表A(小表),表B(大表)
1.select * from A where cc in (select cc from B) //效率低,用到了A表上的cc列的索引;
select * from A where exists(select cc from B where cc=A.cc) //效率高,用到了B表上的cc列的索引;
2.select * from B where cc in (select cc from A) //效率高,用到了B表上的cc列的索引;
select * from B where exists(select cc from A where cc=B.cc) //效率低,用到了A表上的cc列的索引;
如果查询语句使用了not in,那么内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引,所以无论哪个表大,用not exists都比not in要快。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/22012035/viewspace-694336/
,如需转载,请注明出处,否则将追究法律责任。