哪个效率高?查询与子查询或连接表
以下是查询同样的目的 两个例子(在这个例子中,我想从那里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';
哪个更好或更高效,为什么? (我知道这是一个小例子,但我想弄清楚,这对于复杂的情况以及对于大型数据库来说是很好的。)
作为一个一般的经验法则:
如果您使用子查询,你迫使Oracle使用一定的执行路径(即它必须执行的子查询,才可以执行外部查询)
如果您使用连接,Oracle可以自由选择它认为最有效的路径。
因此我会经常参加子查询。因人而异。
我不明白:**为什么**子查询强制Oracle使用某个执行路径?如果你不知道为什么,是什么让你认为这通常是真的? – onedaywhen 2012-02-06 08:37:37
因为你不能在外部位上工作,直到你得到内部位的结果。 (作为一个例子,想象它就像x =(5 *(4 + 2))。在你可以进行外部乘法之前,你必须先做内部(4 + 2)。)注意,优化器有可能能够去解决内部/外部结构问题,但根据我的经验,情况往往不是这样。 – cagcowboy 2012-02-06 08:43:20
保留你的类比,优化器应该能够通过移除'内部'元素(即x =(5 * 4 + 5 * 2))来转换它。 – onedaywhen 2012-02-06 10:03:09
我的经验是,在Oracle中,扁平查询(即,与连接相比)通常比使用子查询的等效查询更高效。看起来在更复杂的情况下,Oracle优化器找不到查询路径,对于使用子查询的查询。在SQL Server,DB2,Ingres和Sybase中,我的经验是它没有什么区别 - 无论您是使用扁平化查询还是带有子选择的查询,这些DBMS都具有可找到相同查询路径的优化器。
我没有足够的其他DBMS经验来评论这些。
但这只是我的经验。如果您发现特定查询或特定数据集的不同结果,我不会感到惊讶。最好的办法是尝试两种方式,并根据自己的情况了解哪种查询效果更好。
在我经验,只要子查询和JOIN 意味着同样的事情,Oracle将执行它们同样快。
人们经常重写他们的疑问,并认为他们一直保持等价,实际上他们引入了细微的差异。例如,OP的查询是否意味着相同的事情取决于salesman_name
是否是PRIMARY KEY(或UNIQUE)。如果不是,这些查询不再意味着同样的事情。这就是说,如果真的存在某些情况(如其他人所指出的那样),那么我并不会感到惊讶,因为在这种情况下,Oracle实际上确实会产生大不相同的执行计划。您的里程可能会有所不同,但一如既往 - 衡量有代表性的数据量,不要盲目地假设其中一方。
这个问题根本没有答案。即使你的表结构没有改变,查询也可以随着时间的推移获得不同的执行路径,这取决于数据量,索引,约束,绑定变量窥视,以及其他一些因素。整本书都是关于这个主题的。
cagcowboy的回答是不正确的。Oracle会重写你的查询来提供它认为最好的执行计划。像你描述的查询经常被subquery unnesting转换。我的猜测是10次中有9次,类似于你描述的查询将具有相同的执行计划。
在我看来,先从什么是最可读的,什么会令它清晰的给别人读你的代码(或自己,阅读它从现在起半年),你的目的是什么。如果您的查询运行速度慢得令人难以接受,请尝试优化它。你认为
正如布兰科Dimitrijevic指出,这两个查询是相同的往往是不等价的。在你的两个例子中,如果salesman_name不是唯一的,你的第一个查询将抛出一个ORA-01427: single-row subquery returns more than one row
异常,但你的第二个例子会正常工作。
>没有问题,它只是一个例子,如果它应该返回多行,我可以在''处使用'in'。 – Patriks 2012-02-08 04:49:27
在某些情况下_sub-query_比加入表格更好, 一旦我遇到>何时,表格中有成千上万的行,并且我使用查询(作为我的问题中的第二个),它需要大约一分钟才能检索数据,然后我用_sub-query_ type查询替换它是很好的。 – Patriks 2012-02-08 04:56:41
我认为它会发生,因为 '选择S1 * 从推销员S1,S2业务员那里 = s1.city s2.city 和s2.salesman_name = 'Patriks';' 在这个例子中,SQL首先需要比较所有s1的行与s2的行一起查找要加入的匹配行。因此它需要以匹配X * X倍(X =没有行的。) 和在 的情况下'SELECT * FROM推销员 其中salesman.city = (从推销员 其中salesman_name ='Patriks选择城市 ' );' 它只需要将内侧行与只有内行查询返回的一行进行比较。所以在这种情况下,我发现sub_query更好 – Patriks 2012-02-08 04:57:28
http://stackoverflow.com/questions/2577174/join-vs-subquery – amd 2012-02-06 08:07:33