2

2 つのクエリがあり、どちらがパフォーマンスとメモリの点で優れているかを理解したいと考えています。これら 2 つの代替案も歓迎します。

クエリ 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 は 500,000 行から数百万行を超える非常に大きなテーブルであり、テーブル a は比較的小さいです。

私の要件は、テーブル a から id (id1 または id2) が 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

3 に答える 3

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つの異なる実行プランを使用するのに役立ちますOR

次のインデックスを作成する必要があります。

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)。正確にこの方法で作成する必要があります。

于 2009-07-15T15:12:10.817 に答える