前言
我们在进行一些sql查询的时候,经常会用到in ,not exist等那么这些究竟有什么区别吗,今天我们来讲一下。
in: in是把外表和内表作hash连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。
嵌套循环(Nested Loop)就是先扫描一个驱动表,然后再拿着扫描出来的记录一条一条去另外一个表中去查找匹配。如果驱动表上有索引,那样查找速度更快些。如果驱动表的返回的记录特别的大,那么效率不是很高。这种方式适合返回少量行的查询。
哈希连接(Hash Join),先扫描一张表,将表中的Key进行哈希,根据哈希结果装进不同的“桶”中,然后再扫描另外一个表的Key,进行Hash之后对应之前的桶。这样就能快速在内存中对记录进行匹配。如果查询返回的记录很少,则效率不高,因为他是对每个Key进行扫描并做Hash处理。如果返回大量行,则这种方式的处理效率是很高的。
请尽量不要使用not in(它会调用子查询),而尽量使用not exists(它会调用关联子查询)。如果子查询中返回的任意一条记录含有空值,则查询将不返回任何记录。如果子查询字段有非空限制,这时可以使用not in,并且可以通过提示让它用hasg_aj或merge_aj连接。
如果查询语句使用了not in,那么对内外表都进行全表扫描,没有用到索引;而not exists的子查询依然能用到表上的索引。所以无论哪个表大,用not exists都比not in 要快。
总结:
IN: 确定给定的值是否与子查询或列表中的值相匹配。使用IN时,子查询先产生结果集,然后主查询再去结果集中寻找符合要求的字段列表,符合要求的输出,反之则不输出。
EXISTS: 给定一个子查询,检测行的存在。它不返回列表的值,只返回一个True或False。其运行方式是先运行主查询一次,再去子查询中查找与其对应的结果,如果子查询返回True则输出,反之则不输出。再根据主查询中的每一行去子查询中查询。
由于IN操作符需要进行确切地比较,而EXISTS只需要验证存不存在,所以使用IN将会比使用EXISTS花费更多的成本,因此能使用EXISTS替代IN的地方,应该尽量使用EXISTS。另外,尽量使用NOT EXISTS替代NOT IN,使用EXISTS替代DISTINCT。
EXISTS与连接查询性能比较:
使用连接查询的效率要比使用EXISTS的效率高。当两张表的数据量不大时,使用二者之一就可以,当其中一张表的数据量巨大,或者两张表的数据量都很大的时候,则最好使用连接查询的方式。