Oracle查询优化程序是否将子句应用于子查询或视图的顶级位置?

时间:2015-10-15 07:46:14

标签: sql oracle performance query-optimization

Oracle文档称Oracle查询引擎首先执行子查询和视图,然后执行顶级查询。作为一个自然的结果,Oracle不允许您在子查询中引用顶级查询的字段值(MSSQL允许这样)您需要构建一个自给自足的子查询并将结果连接到顶级查询

之后我的问题是:Oracle查询优化器是否在执行期间将顶级查询的“where子句”应用于子查询(如果适用)?

假设我有一个子查询或视图,当单独运行时返回一百万行但是当与顶级查询结合使用时,由于join子句或顶部的where子句,将只使用其中的1000行级别查询。 Oracle是否尝试从子查询中引入所有百万行并在连接期间过滤掉不必要的行,或者Oracle查询优化器是否将连接子句或顶级查询中的子句移到子查询中,从而只带来一部分行?

请不要给我明显的答案说:“这样的查询写得不好,我需要重写我的查询”。有时会出现技术或非技术限制,所以我可能无法做到这一点。

我知道MSSQL查询优化器会为子查询和视图执行此操作,但由于Oracle表示将首先执行子查询,因此我需要询问。 Oracle查询优化器会这样做吗?

编辑:以下内容可用作示例查询。查询可能在逻辑上不合适,但它确实代表了我的问题的样本。子查询返回所有销售,但顶级查询仅使用今年的销售。 Oracle是否计算了所有销售额或仅计算今年的销售额?

select u.user_fullname, s.date, s.total
from users u
     inner join ( select userID, date, sum(total) as total       
                 from sales
                 group by userID, date
               ) s on s.userID = u.userID
where s.date > '2015-01-01'

1 个答案:

答案 0 :(得分:1)

Oracle经常在不同级别的查询之间移动条件。这称为谓词推送。逻辑限制可能会阻止子查询和内联视图引用顶级项,但该限制不适用于Oracle执行的转换查询。

此功能已在Oracle中使用了很长时间。文档中有很多引用,甚至还有一些hints来帮助控制它。 (虽然一般情况下你不需要使用提示。)据我所知,没有任何消息来源可以解释它何时可以工作,但它应该能够在你的例子中工作。在许多情况下,谓词推送是可能的,但未启用,因为优化器认为它没有意义。

这个简单的例子显示谓词推动:

--Create a simple table.
drop table test1;
create table test1(a number primary key, b number);
insert into test1 select level, 1 from dual connect by level <= 100000;
commit;
begin
    dbms_stats.gather_table_stats(user, 'TEST1');
end;
/

--Create a very slow function.
create or replace function very_slow(p number) return number authid current_user is
begin
    execute immediate 'begin dbms_lock.sleep(1); end;';
    return 1;
end;
/

--This query only takes 1 second.
--Without predicate pushing it would take hours. 
select *
from
(
    select *
    from test1
    where b = very_slow(b)
)
where a = 1;