<P></P><P>这个问题一直是被热烈讨论的问题,也是很容易被滥用。时常可以在网上看到诸如此类的观点:使用IN代替EXISTS(使用EXISTS代替IN)会提高语句的执行速度,然后通过实例证明其观点发现果然IN比EXISTS要快很多(使用EXISTS代替IN会快很多)。 通过阅读官方文档可以得知:实际上IN和EXISTS并不存在孰优孰劣,谁代替谁的问题。实际上Oracle从9ir2这个版本开始会跟据实际情况进行In和Exists的相互转换,因此可以说大多数情况下是等效的。 官方文档的原文如下: In certain circumstances, it is better to use IN rather than EXISTS. In general, if the selective predicate is in the subquery, then use IN. If the selective predicate is in the parent query, then use EXISTS. 翻译: 在某种情况,使用In要比Exists更好一些。通常情况下,如果选择谓词在子查询语句中,使用IN更好;如果选择谓词在父查询语句中,那就使用EXISTS。 Note: This discussion is most applicable in an OLTP environment, where the access paths either to the parent SQL or subquery are through indexed columns with high selectivity. In a DSS environment, there can be low selectivity in the parent SQL or subquery, and there might not be any indexes on the join columns. In a DSS environment, consider using semi-joins for the EXISTS case. 翻译: 备注:这样的讨论在OLTP环境中更适用一些,通常情况下对父或子查询语句的访问通过具有良好选择性的索引列来进行的。而在DSS环境中,访问子或父查询语句都是比较的选择性的或者没有任何索引列。在DSS环境中可以考虑使用Exists语句。 Sometimes, Oracle can rewrite a subquery when used with an IN clause to take advantage of selectivity specified in the subquery. This is most beneficial when the most selective filter appears in the subquery and there are indexes on the join columns. Conversely, using EXISTS is beneficial when the most selective filter is in the parent query. This allows the selective predicates in the parent query to be applied before filtering the rows against the EXISTS criteria. 翻译: 有时候,oracle会重写子查询。当用选择性特征在子查询中,使用IN子句更有优势。当大多数选择过滤条件在子查询并且索引在连接字段上时,这样做是最有利的。相反,利当大多数选择性过滤条件在父查询中,使用EXISTS更有利。这样在先过滤记录而非EXISTS条件之前允许使用父查询中的选择谓词。 例1 SELECT /* EXISTS example */ e.employee_id, e.first_name, e.last_name, e.salary FROM employees e WHERE EXISTS (SELECT 1 FROM orders o /* Note 1 */ WHERE e.employee_id = o.sales_rep_id /* Note 2 */ AND o.customer_id = 144); /* Note 3 */ 将会被解析成 SELECT /* IN example */ e.employee_id, e.first_name, e.last_name, e.salary FROM employees e WHERE e.employee_id IN (SELECT o.sales_rep_id /* Note 4 */ FROM orders o WHERE o.customer_id = 144); /* Note 3 */ 例2 SELECT /* IN example */ e.employee_id, e.first_name, e.last_name, e.department_id, e.salary FROM employees e WHERE e.department_id = 80 /* Note 5 */ AND e.job_id = 'SA_REP' /* Note 6 */ AND e.employee_id IN (SELECT o.sales_rep_id FROM orders o); /* Note 4 */ 将会被解析成 SELECT /* EXISTS example */e.employee_id, e.first_name, e.last_name, e.salary FROM employees e WHERE e.department_id = 80 /* Note 5 */ AND e.job_id = 'SA_REP' /* Note 6 */ AND EXISTS (SELECT 1 /* Note 1 */ FROM orders o WHERE e.employee_id = o.sales_rep_id); /* Note 2 */</P><P></P>
|