oracle中查询的CPU使用率很高

时间:2013-01-22 12:54:47

标签: oracle unix oracle11g cpu-usage sunos

我有这样的查询...

SELECT cust_num, year,credit_cust FROM
(SELECT cust_num, year,credit_cust,
ROW_NUMBER () OVER(PARTITION BY cust_num, year ORDER BY credit_cust DESC) rnk
FROM credit_cust PARTITION (YEAR_2010)
)
WHERE rnk=1

执行此查询时,托管数据库的服务器的CPU使用率至少增加35%。当服务器中的负载很高时,这确实存在问题,因为有时CPU使用率达到100%。

要求:

数据如下......

Cust_num  Year    Credit_cust
  456     2010       Y
  456     2010       N
  456     2009       N
  456     2009       N

我希望查询只返回下面给出的记录......

Cust_num  Year    Credit_cust
  456     2010       Y
  456     2009       N

注意:我已使用ROW_NUMBER()作为GROUP BY子句的变通方法。因为,之前,我认为它只是导致CPU使用率高的GROUP BY子句

备用查询(其CPU使用率> 35%)

SELECT   cust_num, YEAR, MAX (credit_cust)
    FROM credit_cust PARTITION (year_2010)
GROUP BY cust_num, YEAR


Server : Sun OS 5.10
Database : Oracle 11g (11.2.0.2.0 -64bit)

credit_cust表的结构如下......

CREATE TABLE CREDIT_CUST
(
  CUST_NUM          NUMBER,
  YEAR     NUMBER,
  CREDIT_CUST  CHAR(1)
)
TABLESPACE PARTITION_01
PARTITION BY RANGE (YEAR) 
SUBPARTITION BY HASH (CUST_NUM)
(  
  PARTITION YEAR_2009 VALUES LESS THAN (2010)
    SUBPARTITIONS 16 STORE IN (PARTITION_01,PARTITION_02,PARTITION_03,PARTITION_04,PARTITION_05,PARTITION_06,
                               PARTITION_01,PARTITION_02,PARTITION_03,PARTITION_04,PARTITION_05,PARTITION_06,
                               PARTITION_01,PARTITION_02,PARTITION_03,PARTITION_04),  
  PARTITION YEAR_2010 VALUES LESS THAN (2011)
    SUBPARTITIONS 1 STORE IN (PARTITION_01))
PARALLEL ( DEGREE 16 INSTANCES 1 );

请告诉我为什么会出现这个问题。如果需要更多详细信息,请与我们联系。

EXPLAIN PLAN:

PLAN_TABLE_OUTPUT

Plan hash value: 3927595547

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name                           | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                                |    29M|  1179M|       |  3937   (3)| 00:00:01 |       |       |        |      |            |
|   1 |  PX COORDINATOR                |                                |       |       |       |            |          |       |       |        |      |            |
|   2 |   PX SEND QC (RANDOM)          | :TQ10001                       |    29M|  1179M|       |  3937   (3)| 00:00:01 |       |       |  Q1,01 | P->S | QC (RAND)  |
|*  3 |    VIEW                        |                                |    29M|  1179M|       |  3937   (3)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|*  4 |     WINDOW SORT PUSHED RANK    |                                |    29M|   364M|   674M|  3937   (3)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   5 |      PX RECEIVE                |                                |    29M|   364M|       |  3937   (3)| 00:00:01 |       |       |  Q1,01 | PCWP |            |
|   6 |       PX SEND HASH             | :TQ10000                       |    29M|   364M|       |  3937   (3)| 00:00:01 |       |       |  Q1,00 | P->P | HASH       |
|*  7 |        WINDOW CHILD PUSHED RANK|                                |    29M|   364M|       |  3937   (3)| 00:00:01 |       |       |  Q1,00 | PCWP |            |
|   8 |         PX BLOCK ITERATOR      |                                |    29M|   364M|       |    34   (3)| 00:00:01 |     1 |     1 |  Q1,00 | PCWC |            |
|*  9 |          TABLE ACCESS FULL     | CREDIT_CUST                    |    29M|   364M|       |    34   (3)| 00:00:01 |   228 |   228 |  Q1,00 | PCWP |            |
----------------------------------------------------------------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("RNK"=1)
   4 - filter(ROW_NUMBER() OVER ( PARTITION BY "CUST_NUM","YEAR" ORDER BY INTERNAL_FUNCTION("CREDIT_CUST") DESC )<=1)
   7 - filter(ROW_NUMBER() OVER ( PARTITION BY "CUST_NUM","YEAR" ORDER BY INTERNAL_FUNCTION("CREDIT_CUST") DESC )<=1)
   9 - filter("YEAR"=2010)

Note
-----
   - dynamic sampling used for this statement (level=5)

2 个答案:

答案 0 :(得分:1)

我有两点建议:

  1. 正确分区表格。你有一个subpartionion分区而另一个没有(一个子分区)。分区中的许多年份并不明显。我会使用Year的年度分区和cust上的哈希子分区(每个分区8或16个子分区。如果表格很大并且你有很多处理器,则使用16个。)

  2. 您的查询将在2007年,2008年,2009年,2010年返回客户的结果。您确定要四年吗?如果您只想要2010,则应在year = 2010子句中指定where,并且不需要在分析函数中按年分区,这有助于排序(消耗CPU和TEMP空间)。

  3. 查询将如下:

    SELECT cust_num, year,credit_cust 
    FROM
      (SELECT cust_num, year,credit_cust,
       ROW_NUMBER () OVER(PARTITION BY cust_num ORDER BY credit_cust DESC) rnk
       FROM credit_cust
       WHERE YEAR=2010
       )
    WHERE rnk=1;
    

    一般来说,最好选择带有where子句的分区而不是指定分区名称(也更容易)

答案 1 :(得分:0)

由于并行性,此查询使用大量CPU。该表格设置为DEGREE 16。默认情况下,您的查询将使用16或32个并行服务器,具体取决于它们是否正在排序。

分区选项和查询执行计划在此处不直接相关。即使它们不正确,“坏”查询通常也不会每秒消耗大量资源。

有许多可能的解决方案,具体取决于您要禁用并行度的级别。以下是一些常见的解决方案:

  1. 声明级/*+ no_parallel(credit_cust) */
  2. 会话级alter session disable parallel query;
  3. 对象级alter table cust parallel 1;
  4. 系统级alter system set parallel_max_servers = 0;
  5. 但在改变任何事情之前要仔细考虑。如果使用不当,其中一些解决方案可能是灾难性的。您需要很好地理解并行性,系统资源以及系统的使用方式。像往常一样,一个好的起点是manual