2016-11-23 14 views
3

私は実行に17秒かかるクエリがあります。 FIPS、STR_DT、END_DTにインデックスを適用しましたが、それでも時間がかかります。どのようにパフォーマンスを向上させることができますか?Oracleでの結合クエリの改善

マイクエリ:

SELECT /*+ALL_ROWS*/ K_LF_SVA_VA.NEXTVAL VAL_REC_ID,  a.REC_ID, 
    b.VID, 
    1 VA_SEQ, 
    51 VA_VALUE_DATATYPE, 
    b.VALUE VAL_NUM, 
    SYSDATE CREATED_DATE, 
    SYSDATE UPDATED_DATE 
    FROM CTY_REC a JOIN FIPS_CONS b 
ON a.FIPS=b.FIPS AND a.STR_DT=b.STR_DT AND a.END_DT=b.END_DT; 


DESC CTY_REC; 

Name    Null Type   
------------------- ---- ------------- 
REC_ID     NUMBER(38)  
DATA_SOURCE_DATE   DATE   
STR_DT     DATE   
END_DT     DATE   
VID_RECSET_ID   NUMBER   
VID_VALSET_ID   NUMBER   
FIPS      VARCHAR2(255) 


DESC FIPS_CONS; 

Name   Null  Type   
------------- -------- ------------- 
STR_DT     DATE   
END_DT     DATE   
FIPS     VARCHAR2(255) 
VARIABLE    VARCHAR2(515) 
VALUE     NUMBER   
VID   NOT NULL NUMBER   

は計画を説明:

Plan hash value: 919279614 

-------------------------------------------------------------- 
| Id | Operation   | Name       | 
-------------------------------------------------------------- 
| 0 | SELECT STATEMENT |        | 
| 1 | SEQUENCE   | K_VAL       | 
| 2 | HASH JOIN   |        | 
| 3 | TABLE ACCESS FULL| CTY_REC      | 
| 4 | TABLE ACCESS FULL| FIPS_CONS      | 
-------------------------------------------------------------- 

私はテーブルの記述を追加し、私のクエリのための計画を説明してきました。

+1

/*+ all_rows */を置き換えますか?クエリから投影される行の数はいくつですか?行のどの部分が他の表の行と一致しませんか?シーケンスのキャッシュ値は何ですか? –

+0

完全な実行計画を表示できますか?行見積もりとコスト列(おそらくTmpSpc)を含めて –

答えて

3

を、およびシーケンスの設定に関する情報がなくても、あなたは、各テーブルの行数を使用している、とクエリから投影された行の総数です。実行計画がすべての行を返すための最も効率的な計画である可能性があります。

オプティマイザは、索引がパフォーマンスに影響しないとはっきりと考えています。これは、最初の行ではなくすべての行に対して最適化を行う場合によく発生します。インデックスベースのアクセスは、一度に1つの行と1つの行であるため、ブロックごとのマルチブロックフルスキャンよりも本質的に遅い可能性があります。

Oracleが使用しているハッシュ結合は、データ・セットを結合する非常に効率的な方法です。ハッシュ・テーブルが大きすぎてディスクに流出しない限り、合計コストは2つのテーブルのフル・スキャンよりわずかに多いだけです。ハッシュテーブルがディスクに流出しているかどうかを判断できるようにするために、実行に関する詳細な統計情報が必要です。ソリューションであれば、インデックスではなくメモリ管理だけが変更される可能性があります。

シーケンスのキャッシュ値が非常に低く、レコード数が多い場合は、SQL実行を保持している可能性があります。さらに詳しい情報が必要です。各行のシーケンシャルな識別子を生成する必要がある場合は、ROWNUMを使用できます。

+1

私はこの答えが好きです。あなたが正しいです、完全なテーブルスキャンは悪いことではありません。時には、データにアクセスする最も効率的な方法です。もう一度、ハッシュ結合は2つのテーブルを結合する素晴らしいテクニックです。 –

0

これは、基本的にはあなたのクエリです:

SELECT . . . 
FROM CTY_REC a JOIN 
    FIPS_CONS b 
    ON a.FIPS = b.FIPS AND a.STR_DT = b.STR_DT AND a.END_DT = b.END_DT; 

あなたは(FIPS, STR_DT, END_DT)に複合インデックスが欲しい、おそらく両方のテーブルの上:

create index idx_cty_rec_3 on cty_rec(FIPS, STR_DT, END_DT); 
create index idx_fipx_con_3 on cty_rec(FIPS, STR_DT, END_DT); 

は実際には、一つだけはおそらく必要であるが、両方がオプティマイザを与えましたクエリを改善するための選択肢が増えました。

+0

私はすでにこれらを持っています。 – dang

0

あなたが持っている必要があり、少なくともテーブルの上にこれら二つのインデックス:

  • CTY_REC(FIPS、STR_DT、END_DT)(はFIPS、STR_DT、END_DT)

はまだすることができ

  • FIPS_CONS代わりにインデックスをカバーして高速化する:

    • CTY_REC(FIPS、STR_DT、END_DT、REC_ID)
    • それの顔にFIPS_CONS(FIPS、STR_DT、END_DT、VALUE、VID)
  • +0

    必要なROWIDと空白の両方を含めると、これらの索引が表より大きくなることがあります。 –

    +0

    @David Aldridge:はい、インデックスが大きくなることがありますが、これを使用しない理由は考えられません。 –

    0

    あなたはインデックスを使用するオプティマイザを駆動する場合、
    は、テーブルにあるどのように多くの行/*+ first_rows */

    関連する問題