2

こんなお問い合わせが・・・

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

このクエリを実行すると、DB がホストされているサーバーの 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

注: GROUP BY 句の回避策として ROW_NUMBER() を使用しました。以前は、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 );

この問題が発生する理由を教えてください。さらに詳細が必要な場合はお知らせください。

計画を説明する:

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)
4

2 に答える 2

1

このクエリは、並列処理のために大量の CPU を使用しています。テーブルは に設定されていDEGREE 16ます。デフォルトでは、並べ替えを行っているかどうかに応じて、クエリは 16 台または 32 台の並列サーバーを使用します。

ここでは、パーティショニング オプションとクエリ実行プランは直接関係ありません。それらが正しくない場合でも、「悪い」クエリは通常、1 秒あたりのリソースを大量に消費することはありません。

並列処理を無効にするレベルに応じて、多くの可能な解決策があります。一般的な解決策を次に示します。

  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;

ただし、何かを変更する前によく考えてください。これらのソリューションの一部は、誤って使用すると悲惨な結果になる可能性があります。並列処理、システム リソース、およびシステムの使用方法について十分に理解している必要があります。いつものように、開始するのに適した場所はマニュアルです。

于 2013-01-23T06:06:03.530 に答える
1

2 つの提案があります。

  1. テーブルを適切に分割します。サブパーティション化されたパーティションとそうでないパーティション (単一のサブパーティション) があります。パーティションの年数は明らかではありません。年ごとの年単位のパーティションと、cust のハッシュによるサブパーティションを使用します (パーティションごとに 8 または 16 のサブパーティション。テーブルが大規模でプロセッサが多数ある場合は 16 です)。

  2. このクエリは、2007 年、2008 年、2009 年、2010 年の顧客の結果を返します。本当に 4 年が必要ですか? 2010年のみが必要な場合は、句で指定するyear = 2010必要whereがあり、分析関数で年ごとにパーティション化する必要はありません。これにより、並べ替えが容易になります(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 句でパーティションを選択する方が適切です (これも簡単です)。

于 2013-01-22T13:19:59.660 に答える