只要百度not in和not exists,清一色的not exists的效率优于not in,毕竟not exists只是去强调是否返回结果集,只是一个bool值,而not in是返回一个结果集,是由大量大量数据构成的。所以一开始我在做的时候写的是not in,然后前辈告诉我效率太低,改成了not exists,结果查询速度特别慢。为什么呢?首先来看看sql语句,本身sql语句特别长,只写出where条件中的not in和not exists筛选部分语句。
not in: where substr(表A.字段A,1,9) not in (select substr(字段B,1,9) from 表B) and 表A.字段C not in (select 字段D from 表C)
not exists:where not exists (select 1 from 表B where substr(表B.字段B,1,9) = substr(表A.字段A,1,9) and not exists (select 1 from 表C where 表C.字段D = 表A.字段C)
主表是表A,大概也就不超过10万的数据量吧,然后前面表A先做过一次inner join和两次left join,inner join排除了表A中将近六分之五的数据,两次left join中一次是替换掉表A中的某个字段的值,另一次多取一次值。这些处理都花极其少的时间。然后现在这么做远远不够,表A还要根据另外两张表中的数据来进行再次过滤。这个行为就是通过两个not in来完成的。一开始借鉴了前辈的提议,用了not exists,毕竟返回一个bool值是大量的节省时间,然后实际结果下来却花了整整3秒多,这对于一个用户来是完完全全不能接受的。为什么原因呢?最后推导出原因肯定是在前一句not exists中的两个substr。表B中大概只有5000不到的数据,然而表A里面却有几万条数据,用表B中的每个值和表A中的每个值都要进行一次比较处理,那会是多么一个庞大的处理!!尽管not exists只是返回一个bool值,但是却忽略了里面select语句中where的处理量,而且还要进行一次substr处理。一开始没有想到再去用not in处理,先想到的用的是视图,因为想去除掉一次substr处理,提前把表A中的数据处理好放到视图里,然后再进行处理。结果更加令人意外,视图更加慢,而且还取不到正确结果。这部分的原因我猜应该是表A里面有两个主键,而我做视图的过程中只取了其中一个主键,但是这个取出的这个主键是受后面那个主键约束的,创建了垃圾数据比较多的视图。(其实我本来也不太会视图,还是前辈教的= =。。)我抱着破罐子破摔的想法把not exists换成了not in,然后奇迹出现了,取完整个数据0.1秒一下级别的,反正一眨眼的时间。。完美的符合了系统不管什么处理都不能超过3秒的要求。。
为什么not in在这种情况下效率远远高于not exists呢?按我一介菜鸟的理解,not exists里面的where处理拖慢了整个速度,况且这次处理本来就是想要返回结果集,况且在这之前已经拿了表A.字段A,最终正确的数据是根据这个字段A来获取的,只要拿出不与从其它两张表不匹配的数据即可,就相当于整理衣柜,把没用的衣服拿出来这一个过程而已。而且字段A,B,C,D都是各个表的主键,不存在null值这种概念,没有必要进行额外的判断。所以最后not in的速度比not exists整整快了3秒有余。
数据库是DB2(不要吐槽,日企就是这么喜欢IBM,顶层终于考虑要换oracle。。。)
一介菜鸟,写的错误的地方,欢迎大神提意见,谢谢~~