2011-11-10 12 views
2

私のクエリをより効率的にする方法を手助けする必要があります。私は決してSQLの専門家ではありませんが、これに関する公正なビットを読んでいますが、私は尋ねる/議論する必要がある時点です。複数の内部結合が非常に遅い

私は、次のクエリを持っている:

SELECT * FROM 
(
SELECT 
a.seq_num seq_num_a, 
a.record_length record_length_a, 
b.record_length record_length_b, 
c.record_length record_length_c 
a.deleted deleted_a, 
b.deleted deleted_b, 
c.deleted deleted_c 
FROM tableA a 
INNER JOIN tableB b 
ON a.reference = b.reference 
AND a.run_id = b.run_id 
INNER JOIN tableC c 
ON a.reference = c.reference 
AND a.run_id = c.run_id 
WHERE a.run_id = 1 
) 
WHERE deleted_a = 'N' 
AND deleted_b = 'N' 
AND deleted_c = 'N' 
ORDER BY seq_num_a; 

私は=「N」を削除することを確認した後、クエリが非常に遅いです - でもちょうどにtableAのために。サブクエリがデータセットを返すと思ってSELECT内の全体のクエリをラップしました。それから、それに対して単純なチェックと順序があります。サブクエリ内のチェックとのパフォーマンスの違いはありません。

run_idに対してインデックスがあり、すべてのテーブルで削除され、tableAのseq_numに対して削除されます。各テーブルには約8000の行があります。

クエリプラン

-------------------------------------------------------------------------------------- 
| Id | Operation      | Name    | Rows | Bytes | Cost | 
-------------------------------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |      |  1 | 112 |  7 | 
| 1 | SORT ORDER BY     |      |  1 | 112 |  7 | 
| 2 | NESTED LOOPS     |      |  1 | 112 |  3 | 
| 3 | NESTED LOOPS    |      |  1 | 79 |  2 | 
| 4 |  TABLE ACCESS BY INDEX ROWID| TABLEC    |  1 | 33 |  2 | 
|* 5 |  INDEX SKIP SCAN   | TABLEC_IDX2   |  1 |  |  2 | 
|* 6 |  TABLE ACCESS BY INDEX ROWID| TABLEA    |  1 | 46 |  | 
|* 7 |  INDEX RANGE SCAN   | TABLEA_IDX5   |  1 |  |  | 
|* 8 | TABLE ACCESS BY INDEX ROWID | TABLEB    |  1 | 33 |  1 | 
|* 9 |  INDEX UNIQUE SCAN   | TABLEB_PK   |  1 |  |  | 
-------------------------------------------------------------------------------------- 

Predicate Information (identified by operation id): 
--------------------------------------------------- 

    5 - access("C"."DELETED"='N') 
     filter("C"."DELETED"='N') 
    6 - filter("A"."REFERENCE"="C"."REFERENCE" AND 
       "A"."RUN_ID"="C"."RUN_ID") 
    7 - access("A"."DELETED"='N') 
    8 - filter("B"."DELETED"='N') 
    9 - access("A"."RUN_ID"="B"."RUN_ID" AND 
       "A"."REFERENCE"="B"."REFERENCE") 

Note: cpu costing is off 
+0

説明しましたか? – r0ast3d

+1

クエリプランとは何ですか?インデックスには 'REFERENCE'カラムも含まれていますか?あなたは "非常に遅い"を定量化できますか?私たちは時間を話していますか?分?秒?各テーブルの8000行のうち、どれだけ 'N'の 'DELETED'がありますか? 'tableA'の' RUN_ID'が1の行はいくつありますか? –

+0

また、削除されたものにはnullが含まれていますか、またはすべてY/Nですか?説明計画を投稿してみてください。 – Wolf

答えて

0
どのような値外

わからない。..オラクルのバージョンに応じて、説明計画が異なる可能性が提供された]を選択します。以前のバージョンでは、ジョインがパフォーマンスを大幅に向上させる前にデータを制限していました。

このように、Aで始まり、bへの結合に必要なレコードの量を最小にすることは、すべてのAから始まり、すべてのbに加わり、すべてのCに加わるよりもずっと速くなりました。句...しかし、クエリオプティマイザの後のバージョンではこれを考慮に入れているので、何の利得もありません...だから... oracleのバージョンは?

SELECT 
a.seq_num seq_num_a, 
a.record_length record_length_a, 
b.record_length record_length_b, 
c.record_length record_length_c 
a.deleted deleted_a, 
b.deleted deleted_b, 
c.deleted deleted_c 
FROM tableA a 
INNER JOIN tableB b 
    ON a.reference = b.reference 
    AND a.run_id = b.run_id 
    AND a.deleted = 'N' 
    and b.deleted = 'N' 
    and a.run_ID = 1 
INNER JOIN tableC c 
    ON a.reference = c.reference 
    AND a.run_id = c.run_id 
    and c.deleted = 'N' 
ORDER BY seq_num_a; 
+0

お返事ありがとうございます。私はこれを実装し、クエリは高速でしたが、私はそれが実行しているものについては遅すぎると思っていたでしょう。 115秒から70秒。削除されたチェックがない場合はわずか0.3秒です。私はOracle9iを使用しています。 – PaulyM

+0

@PaulyMこの増加は、キャッシュや他の無関係な変更が原因である可能性があります。キーは説明計画にあります。一般に、SQLオプティマイザは、ジョインに述語があるか、where句に外部述語があるかどうかは気にしません。両方のメソッドを使用して既知のインデックスでカーディナリティをテストしましたが、各テーブルからの最初の行フェッチとの違いはなく、結合メソッドも変更されませんでした。パフォーマンスは最終的に見る人の目には見えます。また、あなたのスキーマに関する最新の統計情報はありますか? – Wolf

+0

私はWolf&justinに同意します。テーブルの統計はオフになっているようです。達成した利益は、私が期待したものではありません。 @wolf 9iは、私がこれらの変更で異なる実行計画を得ることを期待していたバージョンです。 > 9、dbエンジンは、実行計画を、条件がどこに配置されたかには関わらず変更しました。 – xQbert

関連する問題