SQL:建议在加入前使用'select ... where'过滤表吗?

问题描述 投票:1回答:3

在一般的SQL实践中,更多建议使用以下哪两种变体:

让我们考虑表A与列:1,2,3和表B与列3,4。首先选择过滤表:

select col2,col4 from 
  (select col1,col2 from tabA 
     where tabA.col3='sth') as t
  join tabB using (col2);

或使用普通加入?:

select col2,col4 from tabA 
  join tabB using(col2)
  where col3='sth';

我们可以假设where子句匹配1行。表格大小相近。 Oracle规划人员是否正确处理此类连接,以便创建巨大的连接表然后对其进行过滤?

sql oracle11g
3个回答
1
投票

您的第二个版本是编写查询的绝佳方式,但col4col3不合格的例外情况如下:

select col2, col4
from tabA a join
     tabB b
     using (col2)
where a.col3 = 'sth';

仅仅为了记录,这不是一个自然的联接。这是SQL中的一个单独的构造 - 相当可恶。

根据我的经验,Oracle有一个很好的查询优化器。它将知道如何针对给定条件优化查询。子查询应该对查询计划没有任何影响。 Oracle不会在join之前进行过滤,除非这是正确的做法。


2
投票

使用解释计划在真实表上自行测试,以了解评估的行数。我不相信有可能知道哪个更好,或者是否会有任何差异。例如,可用的索引会对优化程序的方法选择产生影响。

关于你的2个例子,我不喜欢“自然连接”语法(“使用”),所以下面的第一个选项是我认为更常见的方法(where子句直接引用“from table”):

select a.col2,b.col4 
from tabA a
inner join tabB b on a.col2 = b.col2
where a.col3='sth'
;

但您也可以尝试这样的连接条件:

select b.col2,b.col4 
from tabB b
inner join tabA a on b.col2 = a.col2 and a.col3='sth'
;

请注意,这会颠倒表格关系。


1
投票

内部过滤器比外部过滤器执行得更好的唯一情况是(通常是复杂的)情况,其中查询优化器为一个查询选择不同的查询计划而不是另一个查询。

Think of it in the same way as a query hint

通过重新组织查询,您可以影响查询计划,而无需使用hint明确这样做

就更多建议而言,最容易阅读的通常是最好的。即使由于放置过滤器的位置,一个比另一个表现更好,您应该专注于拥有正确的索引以确保良好的性能。

© www.soinside.com 2019 - 2024. All rights reserved.