并行化Oracle联合查询问题

4

我有一个像这样的Oracle查询:

Sub_query1
Union
Sub_query2;

我希望将查询并行化。我在网上搜索后发现,有些人说由于子查询是串行运行的,并且只有在两个子查询完成后 UNION 才会运行,所以 UNION 无法并行化。但也有人说 UNION 可以并行化。

我的问题是:

         (1) can a UNION query be parallezied? if yes, how? if no, why?
         (2) can I just parallelize the two sub queries?

我正在使用Oracle数据库11g企业版发布11.1.0.7.0 - 64位生产版本。

谢谢!


谢谢ruakh,我已经添加了Oracle的版本。 - Gary
这个问题可能更适合dba.stackoverflow.com。 - Colin 't Hart
3个回答

3
我认为你混淆了同时运行两个查询和并行运行查询的概念。SQL是一种描述性语言,由SQL引擎/优化器将其转换为代码。该查询计划包含许多不同的组件,用于从表中检索数据、执行连接、聚合等操作。
Oracle为您的联合查询生成一个查询计划。查询计划的每个组件都可以利用所有可用的处理器(假设满足正确的条件)。然而,每个组件基本上一个接一个地运行(以合理的近似值)。因此,查询的组件是并行化的,尽管两个子查询不会同时运行。
一个建议是,每当你考虑使用UNION时,你应该问自己是否也可以使用UNION ALL。因为UNION ALL更高效,它不需要在最终结果集上删除重复项。

2

是的,正如您已经发现的那样,UNION查询可以并行运行。

要完全理解这里发生的情况,您可能需要阅读关于VLDB和Partitioning Guide中并行执行的内容。

几乎可以在任何地方发生Intra-operation并行性。Inter-operation并行性仅在生产者和消费者之间发生。在这种情况下,UNION(一个消费者)可以一直并行执行。每个子查询(生产者)将并行执行,但不会同时执行。

您可以通过查看查询的活动报告,在下面的示例中看到这种情况发生。

--Create two simple tables
create table test1(a number);
create table test2(a number);

--Populate them with 10 million rows
begin
    for i in 1 .. 100 loop
        insert into test1 select level from dual connect by level <= 100000;
        insert into test2 select level from dual connect by level <= 100000;
    end loop;
end;
/
commit;

--Gather stats
begin
    dbms_stats.gather_table_stats(user, 'TEST1');
    dbms_stats.gather_table_stats(user, 'TEST2');
end;
/

--Run a simple UNION.
select /*+ parallel */ count(*) from
(
   select a from test1 join test2 using (a) where a <= 1000
   union
   select a from test2 join test1 using (a) where a <= 1000
);

--Find the SQL_ID by looking at v$sql, then get the active report
--(which must be saved and viewed in a browser)
select dbms_sqltune.report_sql_monitor(sql_id => 'bv5c18gyykntv', type => 'active')
from dual;

这里是部分输出内容。它难以阅读,但显示了UNION和计划的前11步骤一直在运行。第一个子查询,接下来的9行,在查询的前半部分运行。然后第二个子查询,最后的9行,在查询的后半部分运行。 并行UNION查询的活动报告

1
通过进行一些测试并比较执行计划,我最终找到了一种像这样并行化联合的方法:
select/* +parallel (Result) */ * from
(Sub_query1
Union
Sub_query2) Result;

通过这样做,时间和CPU成本几乎只有串行版本的一半。将并行提示添加到两个子查询中都不会改变时间和CPU成本。


1
你能证明 sub_query1 和 sub_query2 是并行运行的吗?因为据我所知,这将会并行执行 sub_query1 并联合 sub_query2 的并行执行结果。 - Gaurav Soni
我无法从执行计划中证明这两个子查询是并行执行还是串行执行。 - Gary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接