2011-01-06 15 views
0

ガード私は日付の間に月単位のレポートを提供する次のOracle SQLクエリーを持っています.Nov月間は基本的には01novから30novの間の値の合計が必要です。 照会されているテーブルは別のデータベースに存在し、dblinkを使用してアクセスされています。 DT列のタイプはNUMBERです(20101201以前)。Oracle Sql dblinkを使用して結果を返すクエリー

SELECT /*+ PARALLEL (A 8) */ /*+ DRIVING_STATE(A) */ 
TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')- 1,'MM'),'MONYYYY') "MONTH", 
    TYPE AS "TYPE", COLUMN, COUNT (DISTINCT A) AS "A_COUNT", 
    COUNT (COLUMN) AS NO_OF_COLS, SUM (DURATION) AS "SUM_DURATION", 
    SUM (COST) AS "COST" FROM **[email protected]_PROD A** 
     WHERE DT >= TO_NUMBER(TO_CHAR(add_months(SYSDATE,-1),'YYYYMM"01"')) 
     AND DT < TO_NUMBER(TO_CHAR(SYSDATE,'YYYYMM"01"')) 
     GROUP BY TYPE, COLUMN 

クエリの実行に1日かかり、完了していません。 dblinkで私のDBAに提案することができる最適化、またはクエリで実行できるチューニング、または同じものを書き直すことができれば、私に親切にお勧めします。テーブルの上に

UPDATES

テーブルは、日付列、ほぼ10億レコードにpartiontionedれます。私の下

**Plan** 
SELECT STATEMENT REMOTE ALL_ROWSCost: 1,208,299 Bytes: 34,760 Cardinality: 790            
    12 PX COORDINATOR           
     11 PX SEND QC (RANDOM) SYS.:TQ10002 Cost: 1,208,299 Bytes: 34,760 Cardinality: 790           
      10 SORT GROUP BY Cost: 1,208,299 Bytes: 34,760 Cardinality: 790          
       9 PX RECEIVE Cost: 1,208,299 Bytes: 34,760 Cardinality: 790         
        8 PX SEND HASH SYS.:TQ10001 Cost: 1,208,299 Bytes: 34,760 Cardinality: 790        
         7 SORT GROUP BY Cost: 1,208,299 Bytes: 34,760 Cardinality: 790      
          6 PX RECEIVE Cost: 1,208,299 Bytes: 34,760 Cardinality: 790      
           5 PX SEND HASH SYS.:TQ10000 Cost: 1,208,299 Bytes: 34,760 Cardinality: 790     
            4 SORT GROUP BY Cost: 1,208,299 Bytes: 34,760 Cardinality: 790   
             3 FILTER   
              2 PX BLOCK ITERATOR Cost: 1,203,067 Bytes: 15,066,833,144 Cardinality: 342,428,026 Partition #: 11 Partitions accessed #1 - #5 
               1 TABLE ACCESS FULL TABLE CDRR.FRD_CDF_DATA_INTL_IN_P Cost: 1,203,067 Bytes: 15,066,833,144 Cardinality: 342,428,026 Partition #: 11 

私は今日をするつもりです以下のものは、任意の追加のヒントが参考になるTOADからPLANをEXPLAIN与えています。

  1. 私は、最適な 実行計画を与える可能性がある、このテーブルのtablewise統計を収集するつもりです。
  2. パーティションに対してローカルインデックスが作成されているかどうかを確認します。
  3. > =と<の代わりにBETWEENを使用します。
+2

興味があるだけで

WHERE DT >=TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')-1,'MM'),'YYYYMMDD')) AND DT < TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM'),'MM'),'YYYYMMDD')) 

を、どのくらいの時間が直接、リモート・データベース上で実行するために時間がかかりますか?クエリー自体が単に長い時間がかかっている場合は、DB Linkが赤字になっている可能性があります。 –

+0

億行!それは長い時間がかかるのも不思議ではありません! –

答えて

1

このタイプの質問ではいつものように、説明計画が役に立ちます。それは実際にデータベースで何が起こっているのかを理解するのに役立ちます。

リンクを介してデータを送信し、クエリをローカルで実行するのではなく、リモートデータベースでクエリが実行されていることを確認するのが理想的です。これにより、リンクを介して送信されるデータが少なくなります。 DRIVING_SITEヒントはこれを助けることができますが、オラクルはそれにはかなりスマートなので、まったく役に立たないかもしれません。

Oracleは遠隔クエリを実行する方が優れているようですが、まだ問題がある可能性があります。

また、一部の日付変換を簡略化するためにお支払いいただく場合があります。

たとえば、これを置き換えます。これで

TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')- 1,'MM'),'MONYYYY') 

を:

TO_CHAR(add_months(TRUNC(SYSDATE,'MM'), -1),'MONYYYY') 

それはおそらく少しより効率的であるだけでなく、読みやすいです。

は同様に、この置き換え:

WHERE DT >=TO_NUMBER(TO_CHAR(add_months(TRUNC(SYSDATE,'MM'), -1),'YYYYMMDD')) 
    AND DT < TO_NUMBER(TO_CHAR(TRUNC(SYSDATE,'MM'),'YYYYMMDD')) 

あるいは

WHERE DT >=TO_NUMBER(TO_CHAR(add_months(SYSDATE,-1),'YYYYMM"01"')) 
    AND DT < TO_NUMBER(TO_CHAR(SYSDATE,'YYYYMM"01"')) 
+0

ここに説明を掲載しました。親切にintを見てください。 –

+0

@Suresh:並列クエリやパーティションの実行計画を読んだことがないので、probがあまり役に立たない。しかし、ひどく大きなテーブルのように見えます!私はテーブル/パーティションの圧縮が大規模なテーブルに役立つことがわかりましたが、これは実際には10g(11個の方が良い)の静的データの大量ロードでのみ機能しますが、必要に応じて履歴パーティションを圧縮できます。 –

1

複数の問題がある可能性があります。 1.データベースが異なるハードウェアに存在する可能性があるため、ネットワークの速度。 しかし、あなたはこのリンクを参照することができます http://www.experts-exchange.com/Database/Oracle/Q_21799513.html。 同様の問題があります。

+0

ネットワーク速度は良いです。 –

+0

はパラメータの1つだけを強調表示しました – UVM

+0

他のデータベースでクエリを実行できない場合は、欠落しているテーブルを作成します。SQLクエリを調整する必要があります。 – UVM

1

テーブルの構造、制約、インデックス、データ量、結果セットのサイズ、ネットワーク速度、並行性のレベル、実行計画などを知らなくても答えられません。私が調査するでしょう

いくつかの点:

をテーブルが分割されている場合は、統計情報は、クエリが当たっているパーティションに存在していますか?一般的な問題は、統計がデータが挿入される前に空のパーティションに集約されることです。そして、(統計がリフレッシュされる前に)問合せを実行すると、実際にそのパーティションでFTSを使用する必要があるときに、Oracleは索引スキャンを選択します。

はまた、統計に関連する:

WHERE DT >= 20101201 
    AND DT < 20110101 

は、Oracleのバージョンは何あなたにある を更新:

WHERE DT >=TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM')-1,'MM'),'YYYYMMDD')) 
    AND DT < TO_NUMBER(TO_CHAR(TRUNC(TRUNC(SYSDATE,'MM'),'MM'),'YYYYMMDD')) 

が同じ実行計画を生成していることを確認してください?私が求めている理由は、Oracle 10g以降では、この場合に選択されていたグループ別の実装があります(ソートではなくハッシング)。基本的には、日付フィルタ(14ギガバイト)から返された3億4,200万行をソートしているようです。それをバックアップするRAMがありますか?そうしないと、マルチパスのソートが行われ、ディスクに流出します。これはおそらく起こっていることです。

計画によると、約790行が返されます。それは正しい球場にありますか? もしそうなら、ネットワークの問題を除外することができます:)

また、私は完全にその計画の形式に精通していません。テーブルはサブパーティション化されていますか?さもなければ私はパーティション#11参照を取得しません。

関連する問題