哪个有效?查询子查询或连接表

时间:2012-02-06 07:53:53

标签: sql database oracle

以下是出于同一目的的两个查询示例 (在这个例子中,我想要对来自Patriks居住的同一城市的推销员进行优秀。)

select * 
from salesman 
where salesman.city = 
     ( select city 
       from salesman 
       where salesman_name='Patriks'
     );

select s1.* 
from salesman s1,salesman s2 
where s1.city=s2.city 
  and s2.salesman_name='Patriks';

哪个更好或更有效?为什么? (我知道这是一个很小的例子,但我想弄清楚,在复杂情况下这对于大数据库来说会很好。)

4 个答案:

答案 0 :(得分:5)

我的经验是,在Oracle中,扁平查询(即具有连接的查询)通常比使用子选择的等效查询更有效。对于具有子选择的查询,似乎在更复杂的情况下,Oracle优化器找不到查询路径。

在SQL Server,DB2,Ingres和Sybase中,我的经验是没有区别 - 这些DBMS的优化器会找到相同的查询路径,无论您使用的是扁平查询还是带有子选择的查询。 / p>

我没有足够的经验让其他DBMS对这些做出评论。

但那只是我的经历。如果您针对特定查询或特定数据集找到不同的结果,我不会感到惊讶。最好的办法是尝试两种方法,看看哪种查询更适合您的情况。

答案 1 :(得分:5)

作为一般经验法则:

如果使用子查询,则强制Oracle使用某个执行路径(即它必须先执行子查询才能执行外部查询)

如果您使用联接,Oracle可以自由选择它认为最有效的路径。

因此,我总是会在子查询上加入。 YMMV。

答案 2 :(得分:2)

我的体验中,只要子查询和JOIN 意味着同样的事情,Oracle就会同样快速地执行它们。

人们经常会重写他们的查询并认为他们已经保持等效,而实际上他们已经引入了微妙的差异。例如,OP的查询是否意味着相同的事情取决于salesman_name是PRIMARY KEY(还是UNIQUE)。如果不是,则这些查询不再具有相同的含义。

话虽如此,如果确实存在某些情况(正如其他人所指出的那样),我确实不会感到惊讶,其中Oracle确实产生了截然不同的执行计划。您的里程可能会有所不同,但一如既往 - 衡量代表性的数据量,不要盲目地假设一种方式。

答案 3 :(得分:2)

这个问题根本没有答案。即使您的表结构没有改变,查询也可以随着时间的推移获得不同的执行路径,具体取决于数据量,索引,约束,因为绑定变量偷看,以及其他因素。已经写了关于这个主题的全书。

cagcowboy的回答不正确。 Oracle将重写您的查询以提供它认为最佳的执行计划。您描述的查询通常由subquery unnesting转换。我的猜测是,10次中的9次,与您描述的查询类似的查询将具有相同的执行计划。

在我看来,从最可读的东西开始,什么才能使其他人阅读你的代码(或者你自己,从现在起六个月后阅读它),你的意图是什么。如果您的查询运行速度慢得令人无法接受,那么请尝试对其进行优化。

正如Branko Dimitrijevic指出的那样,您认为两个相同的查询通常不相同。在您的两个示例中,如果salesman_name不是唯一的,那么您的第一个查询将抛出ORA-01427: single-row subquery returns more than one row异常,但您的第二个示例将正常工作。