我读过,通常你应该在子查询的结果很大时使用EXISTS
,而在子查询结果很小时使用IN
。
但在我看来,如果必须为每一行重新评估子查询,或者如果可以为整个查询评估一次子查询,那么它也是相关的。
考虑以下两个等效查询的示例:
SELECT * FROM t1
WHERE attr IN
(SELECT attr FROM t2
WHERE attr2 = ?);
SELECT * FROM t1
WHERE EXISTS
(SELECT * FROM t2
WHERE t1.attr = t2.attr
AND attr2 = ?);
前一个子查询可以针对整个查询进行一次评估,后者必须针对每一行进行评估。
假设子查询的结果非常大。这是写这个的最好方法吗?
答案 0 :(得分:1)
这是一个很好的问题。特别是在Oracle中,您可以将每个EXISTS子句转换为IN子句,反之亦然,因为Oracle的IN子句可以处理元组(where (abc) in (select x,y,z from ...
),而其他大多数dbms都不能。
你的理由很好。是的,使用IN子句,您建议一次加载所有子查询的数据,而不是在循环中查找记录。然而,这只是部分正确,因为:
说到这里,Oracle的优化器应该注意到这两个语句实际上是完全相同的,应该生成相同的执行计划。但是经验表明优化器有时候并没有注意到,并且通常优化器出于某种原因使用EXISTS子句做得更好。 (与MySQL不同,但是,在Oracle中,EXISTS似乎优于IN。)
关于你的问题"假设子查询的结果非常大。哪个是写这个的最好方法?",IN子句不可能比EXISTS子句更快。
我经常更喜欢IN子句的简单性,并且大多数人觉得它更具可读性。但是在性能方面,有时最好使用EXISTS(甚至是外连接)。