0

以下の集計クエリのパフォーマンスを改善したいと考えています。

3000 万レコードの T_Search_Detail で、以下のクエリの実行に 12 秒かかりますか? パフォーマンスを改善するための提案をより良く書くことができますか?

プランの説明:

Execution Plan
----------------------------------------------------------
Plan hash value: 651646209
--------------------------------------------------------------------------------------------------
| Id  | Operation                      | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                 |     3 |    42 | 27948   (1)| 00:05:36 |
|   1 |  SORT GROUP BY                 |                 |     3 |    42 | 27948   (1)| 00:05:36 |
|   2 |   VIEW                         |                 |    56 |   784 | 27947   (1)| 00:05:36 |
|   3 |    HASH GROUP BY               |                 |    56 |  1344 | 27947   (1)| 00:05:36 |
|*  4 |     TABLE ACCESS BY INDEX ROWID| T_SEARCH_DETAIL |   898 | 21552 | 27946   (1)| 00:05:36 |
|*  5 |      INDEX RANGE SCAN          | INDEX_CREATE_DT |  1254K|       |  3451   (1)| 00:00:42 |
--------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   4 - filter("TSD"."MATCH_SOURCE" IS NOT NULL AND "TSD"."MATCH_TYPE" IS NOT NULL AND
              "TSD"."MATCH_TYPE" LIKE '%Exact%')
   5 - access("TSD"."CREATE_DT">=TO_DATE(' 2012-12-11 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss') AND "TSD"."CREATE_DT"<TO_DATE(' 2013-04-23 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss'))

テーブル DDL: ここに画像の説明を入力

このクエリは、 T_SearchT_Search_detailの 2 つのテーブルを使用し、FOREIGN_KEYをmatch_idとして使用します。

SELECT   ms,
         SUM(ct)
FROM     ( SELECT  tsd.match_source    ms,
                  tsd.match_type       mt,
                  COUNT(tsd.search_id) ct
         FROM     t_search ts,
                  t_search_detail tsd
         WHERE    tsd.match_source IS NOT NULL
         AND      tsd.match_type   IS NOT NULL
         AND      ts.match_id                = tsd.match_id
         AND      tsd.match_type          LIKE '%Exact%'
         AND
                  (
                           tsd.create_dt >= to_date('12/11/2012', 'MM/DD/YYYY')
                  AND      tsd.create_dt  < (to_date('04/22/2013', 'MM/DD/YYYY')+1)
                  )
         GROUP BY tsd.match_source,
                  tsd.match_type
         )
GROUP BY ms
ORDER BY ms DESC
4

3 に答える 3

1

まず、実行していることに 2 つのレベルの集約は必要ありません。match_source一致するレコードの数を集計してカウントするだけです。

以下は、適切な結合構文を使用した単純化されたバージョンのクエリです。

SELECT  tsd.match_source ms, COUNT(tsd.search_id) ct
FROM t_search ts join
     t_search_detail tsd
     on ts.match_id = tsd.match_id
WHERE tsd.match_source IS NOT NULL AND
      tsd.match_type   IS NOT NULL AND
      tsd.match_type LIKE '%Exact%' and
      tsd.create_dt >= to_date('12/11/2012', 'MM/DD/YYYY') and
      tsd.create_dt  < (to_date('04/22/2013', 'MM/DD/YYYY')+1)
GROUP BY tsd.match_source;

次に、テーブルt_searchがまったく使用されていないように見えます。フィルタリングに使用されるか、行数が増える可能性があります。t_search_detailただし、 のすべてが の1 行に正確に一致すると仮定すると、次のt_searchようになります。

SELECT  tsd.match_source ms, COUNT(tsd.search_id) ct
FROM t_search_detail tsd
WHERE tsd.match_source IS NOT NULL AND
      tsd.match_type   IS NOT NULL AND
      tsd.match_type LIKE '%Exact%' and
      tsd.create_dt >= to_date('12/11/2012', 'MM/DD/YYYY') and
      tsd.create_dt  < (to_date('04/22/2013', 'MM/DD/YYYY')+1)
GROUP BY tsd.match_source;

これにより、次のようなインデックスを使用してパフォーマンスが向上する場合がありますt_search_detail(match_source, match_type, create_dt)

CREATE INDEX tsearchdetail_matchsource_matchtype_createdt
         ON t_search_detail(match_source, match_type, create_dt);

このクエリでは、日付に一致するすべてのレコードを検索する必要があるようです。match_typeフォームのリストを'%EXACT%'有限リストに拡張できますか? その場合は、その行を次のように変更しwhereます。

where . . . and match_type in (<list of exact match types>) . . .

次に、にインデックスが必要です(match_type, create_dt)。ただし、これによりパフォーマンスが大幅に向上するのは、ほとんどの一致タイプが「正確」でない場合のみです。大量のレコードを処理する必要があり、数秒かかる場合があります。

于 2013-05-16T18:07:20.233 に答える
0

SQL のチューニング自体とは別に、クエリの実行中 (およびその後の v$sql_workarea) に v$sql_workarea_active を監視して、クエリがストレージに一時テーブルスペースを使用しているかどうかを確認します。

マルチパス操作はパフォーマンス キラーであり、メモリのサイズを確認してそれらを回避し、できればシングル パス操作を回避する必要があります。そのためには、セッションを手動のメモリ管理に切り替えるか、それぞれのキャッシュ アドバイザ ビューで PGA および SGA サイズの全体的な割り当てを確認する必要がある場合があります。

http://docs.oracle.com/cd/E11882_01/server.112/e16638/memory.htm#i49320

于 2013-05-19T08:30:38.333 に答える