2009-07-15 4 views
2

2つのクエリがあります。パフォーマンスとメモリのどちらが優れているかを理解したいと思います。私はまた、これらの2つのための他の選択肢を歓迎します。Oracleのパフォーマンスとメモリ

クエリ1:ここでは

SELECT DISTINCT a.no, 
    a.id1   , 
    a.id2 
    FROM tbl_b b   , 
     tbl_a a , 
     tbl_c c , 
     tbl_d d 
    WHERE (
      b.id1    = a.id1 
     AND a.id1    = c.id1 
     AND upper(c.flag)  = 'Y' 
     AND c.id1    = d.id1 
    ) 
    OR (
      b.id2    = a.id2 
     AND a.id2    = c.id2 
     AND upper(c.flag)  = 'Y' 
     AND c.id2    = d.id2 
) 
AND d.id3 = 10 

テーブルbとdが表Aは比較的小さいながらに50万人以上の数百万行、 を実行している非常に大規模なテーブルです。

私の要件は、id、id1またはid2のいずれかのidを持つテーブルaのレコードだけをb、c、dテーブルで利用できるようにして、特定の条件を満たすものです。

私が手に持っている別のクエリが

クエリ2:

SELECT DISTINCT a.no, 
    a.id1    , 
    a.id2 
    FROM tbl_a a 
    where exists (select a.id1, a.id2 from   
      tbl_c c where ((a.id1 = c.id1 or a.id2 = c.id2) 
      AND upper(c.active_flag) = 'Y')) 
    and exists (select a.id1, a.id2 from 
      tbl_b b where b.id1 = a.id1 or b.id2 = a.id2) 
    and exists (select a.id1, a.id2 from tbl_d d 
       where (a.id1 = d.id1 or a.id2 = d.id2) 
       AND d.id3 = 10) 

最高のパフォーマンスが賢明ですか?私は、クエリ2はクエリ1よりも少ない領域を占めることを理解しています。 しかし、どのように最適なものを選択しますか?

答えて

4

最良のものを選択する方法は、現実的なデータを試してみて、どちらが最も優れているかを確認することです。論理的に等価なクエリの場合、オプティマイザはAUTOTRACEまたはTKPROFまたは類似のツールを使用して両方とも同じ計画を作成する可能性があります。

+0

こんにちはトニー、私の間違いだった..私はparanthesisを逃した。私は今、クエリを更新しました、それは((aまたはb)とc)私の状態です。 –

+0

OK、カッコについてのコメントを削除しました。 2つのクエリが論理的に同等であることから、私はさらに満足しています。 –

+0

+1、可能であれば、いつでも自分で試してみてください。 – DCookie

1

更新

は、パフォーマンスの詳細については、私のブログにこの記事を参照してください。

この1つは、最も効率的になります。

SELECT a.no, 
     a.id1, 
     a.id2 
FROM tbl_a a 
WHERE EXISTS 
     (
     SELECT 1 
     FROM tbl_b b 
     WHERE b.id1 = a.id1 
     ) 
     AND EXISTS 
     (
     SELECT 1 
     FROM tbl_c c 
     WHERE c.id1 = a.id1 
       AND UPPER(c.flag) = 'Y' 
     ) 
     AND EXISTS 
     (
     SELECT 1 
     FROM tbl_d d 
     WHERE d.id1 = a.id1 
       AND d.id3 = 10 
     ) 
UNION 
SELECT a.no, 
     a.id1, 
     a.id2 
FROM tbl_a a 
WHERE EXISTS 
     (
     SELECT 1 
     FROM tbl_b b 
     WHERE b.id2 = a.id2 
     ) 
     AND EXISTS 
     (
     SELECT 1 
     FROM tbl_c c 
     WHERE c.id2 = a.id2 
       AND UPPER(c.flag) = 'Y' 
     ) 
     AND EXISTS 
     (
     SELECT 1 
     FROM tbl_d d 
     WHERE d.id2 = a.id2 
       AND d.id3 = 10 
     ) 

OracleORの条件を最適化するにはあまり適していません。

クエリを分離すると、オプティマイザは、2つの異なる実行計画をそれぞれの部分に対して使用するのに役立ちます。あなたは、次のインデックスを作成する必要があり

tbl_b (id1) 
tbl_b (id2) 
tbl_c (id1, UPPER(flag)) 
tbl_c (id2, UPPER(flag)) 
tbl_d (id1, id3) 
tbl_d (id2, id3) 

UPPER(flag)上のファンクション索引を注意してください、あなたはまさにこの方法でそれを作成する必要があります。

+0

クエリを変更しました - ( 'y'、 'Y')!=( 'Y') Unionは返された結果セットに対してソートを行います。 最初の選択肢が見つかりません "AND d.id3 = 10" – user60890

+2

@glenn:元のクエリは、フラグIN( 'y'、 'Y')に相当するUPPER(フラグ)= 'Y'です。 – Quassnoi

+2

@glenn: UNIONは必ずしもソートを引き起こすわけではありません。これはオプティマイザによって選択されたメソッドに依存します:SORT UNIQUEまたはHASH UNIQUE、後者は – Quassnoi

1

あなたに確かな答えを与えるのに十分な情報がありません。インデックスはありますか? TBL_Cの場合、FLAG = 'Y'のレコードの割合はどれくらいで、そのテーブルにいくつのレコードがありますか?テーブルTBL_Dの場合、ID3 = 10のレコードはいくつですか?

Tonyはautotraceとtkprofを使って、どちらが最も仕事量が少ないかを知りました。私は通常、それぞれのSQL_PLANを取得し、コストが私の期待どおりであれば実行します。データの量と適切なインデックスでは、1秒以上2秒以上は実行しないでください。

+0

インデックスが必要なことを示すのに十分な情報があります。 – jva

+0

これについてはどうですか?テーブルはどれくらい大きいですか?私たちはレコードの数は知っていますが、どれくらい大きいかはわかりません。 FLAGフィールドは、レコードの1%または99%でyesに設定されていますか? TBL_Dと同じですか? フルスキャンを使用してから逆にインデックスを使用するクエリでは、さらに多くの問題が発生しました。インデックスは邪悪ではありませんが、すべてを解決するわけでもありません。 – user60890

関連する問題