oracle - oracle 中查询的 CPU 使用率过高

标签 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 子句的解决方法。之前,我认为这只是 GROUP BY 子句导致 CPU 使用率高

备用查询:(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 );

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

解释计划:

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)

最佳答案

我有两个建议:

  1. 正确对表进行分区。您有一个分区被子分区,另一个分区未被子分区(单个子分区)。分区中的年份数并不明显。我会在 cust 上使用按年进行年度分区和按哈希进行子分区(每个分区 8 或 16 个子分区。如果表很大并且您有很多处理器,则为 16。)

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

查询如下:

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子句选择分区,而不是指定分区名称(也更容易)

关于oracle - oracle 中查询的 CPU 使用率过高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14459057/

相关文章:

database - 如何在sqlplus中打开已经创建的数据库

sql - 使用多个替换函数调用进行查询 - 如何提高性能?

sql - 为空 vs. 等于空

linux - 以#!/bin/rm 开头的脚本如何删除自身?

jdbc - Oracle defaultNChar=true SLOW on NCHAR/NVARCHAR2

mysql - 创建 View 以从多个表中获取值

shell - 是否可以在 unix bash 脚本中嵌套 Here Document?

linux - 如何在 unix 中将一个文件的第 10 行到第 15 行复制到另一个文件中?

oracle - 是否可以使用 sql%rowcount 进行 SELECT?

directory - 什么是 Oradiag_<user> 文件夹?