并行性不会提供任何性能提升

时间:2014-04-23 20:04:06

标签: sql oracle parallel-processing

我的选择查询变得非常慢,所以我开始尝试并行,但似乎我没有看到任何性能提升。

SELECT /*+ PARALLEL(4) */ count(\*) FROM builds;  -- 35 sec  
SELECT count(\*) FROM builds;                     -- 35 sec  

有人可以解释如何使用并行性加速查询吗?

2 个答案:

答案 0 :(得分:2)

并行索引快速全扫描可能是使用主键计算非常大的表的记录数的最快方法。

并行提示没有提高原始查询的性能有很多原因。如下所示,最可能的原因是您的查询正在将并行全表扫描串行索引快速全扫描进行比较。

示例架构

--Sample schema: Create table, insert 30M rows, add a primary key, gather stats.
--This takes a few minutes to setup.
create table test1(c1 number,c2 number,c3 number,c4 number,c5 number) nologging;
begin
    for i in 1 .. 300 loop
        insert /*+ append */ into test1
        select level+(i*100000),level,level,level,level
        from dual connect by level <= 100000;
        commit;
    end loop;
end;
/
alter table test1 add constraint test1_pk primary key(c1);
begin
    dbms_stats.gather_table_stats(user, 'test1');
end;
/

解释计划

--#1: Parallel hint - parallel full table scan.
explain plan for select /*+ parallel(test1) */ count(*) from test1;
select * from table(dbms_xplan.display);

--------------------------------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
--------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     1 |    73  (22)| 00:00:01 |        |      |            |
|   1 |  SORT AGGREGATE        |          |     1 |            |          |        |      |            |
|   2 |   PX COORDINATOR       |          |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM) | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |
|   4 |     SORT AGGREGATE     |          |     1 |            |          |  Q1,00 | PCWP |            |
|   5 |      PX BLOCK ITERATOR |          |    30M|    73  (22)| 00:00:01 |  Q1,00 | PCWC |            |
|   6 |       TABLE ACCESS FULL| TEST1    |    30M|    73  (22)| 00:00:01 |  Q1,00 | PCWP |            |
--------------------------------------------------------------------------------------------------------


--#2: Regular count(*) - serial index fast full scan.
explain plan for select count(*) from test1;
select * from table(dbms_xplan.display);

--------------------------------------------------------------------------
| Id  | Operation             | Name     | Rows  | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |          |     1 |  1270  (32)| 00:00:11 |
|   1 |  SORT AGGREGATE       |          |     1 |            |          |
|   2 |   INDEX FAST FULL SCAN| TEST1_PK |    30M|  1270  (32)| 00:00:11 |
--------------------------------------------------------------------------

--#3: Parallel_index - parallel index fast full scan.
explain plan for select /*+ parallel_index(test1) */ count(*) from test1;
select * from table(dbms_xplan.display);

-----------------------------------------------------------------------------------------------------------
| Id  | Operation                 | Name     | Rows  | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |
-----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT          |          |     1 |  1270  (32)| 00:00:11 |        |      |            |
|   1 |  SORT AGGREGATE           |          |     1 |            |          |        |      |            |
|   2 |   PX COORDINATOR          |          |       |            |          |        |      |            |
|   3 |    PX SEND QC (RANDOM)    | :TQ10000 |     1 |            |          |  Q1,00 | P->S | QC (RAND)  |
|   4 |     SORT AGGREGATE        |          |     1 |            |          |  Q1,00 | PCWP |            |
|   5 |      PX BLOCK ITERATOR    |          |    30M|  1270  (32)| 00:00:11 |  Q1,00 | PCWC |            |
|   6 |       INDEX FAST FULL SCAN| TEST1_PK |    30M|  1270  (32)| 00:00:11 |  Q1,00 | PCWP |            |
-----------------------------------------------------------------------------------------------------------

效果比较

这段代码运行了好几次。第一个,最高的和最低的结果被抛弃,其余的被平均。

alter system flush buffer_cache;
select /*+ parallel(test1) */ count(*) from test1;
alter system flush buffer_cache;
select count(*) from test1;
alter system flush buffer_cache;
select /*+ parallel_index(test1) */ count(*) from test1;


Count(*) (serial index)             -  6.34 seconds
Parallel (parallel full table scan) -  6.20 seconds
Parallel_index (parallel index)     -  2.35 seconds

其他一千个原因,一些警告

也许查询在您的系统上运行相同,因为并行性未启用,未使用或无效。检查解释计划,SQL监控或v $ px_process,以了解使用多少并行度。如果并行度似乎不对,我在this answer中列出了影响DOP的因素列表。

对于I / O和CPU,并行性可以对许多查询产生巨大影响。但35秒绝对是规模的小端。并行查询通常用于需要几分钟或几小时的语句。如此小的查询会有很大一部分开销。即使它运行得更快,您也应该考虑是否值得以更快的速度运行一个查询,而不考虑从其他查询中获取的额外资源。

答案 1 :(得分:1)

听起来Oracle正在进行表扫描以获取Count。并行性无法修复,因为操作是I / O绑定,而不是CPU绑定。

您可以尝试从ALL_TABLES获取它(这应该非常快):

SELECT NUM_ROWS FROM ALL_TABLES WHERE TABLE_NAME = 'builds';