Hitachi

ノンストップデータベース HiRDB Version 9 コマンドリファレンス(UNIX(R)用)


17.6.3 インデクス検索について

〈この項の構成〉

(1) 探索条件にORを指定した検索(その1)

(a) 表示の確認

1表検索の場合に,TABLE SCANとなって性能が悪くないか確認してください。

(b) ベターユース

ORの両辺に同じ条件を指定している場合には,同じ条件をORの外へ抜き出してください。

(c) 理由

  • 1表検索の場合

    抜き出した述語の列にインデクスが定義してあれば,インデクス内のサーチ範囲を小さくし,インデクス内のサーチ時間を短縮できます。

  • 結合検索の場合

    結合条件をOR演算子で結んでいる場合には,結合する表の直積(CROSS JOIN)をしてから,直積結果に対して結合条件を評価します。抜き出した述語が結合条件であれば,ネストループジョイン,又はマージジョインをするので,結合時のデータの突き合わせ回数を削減できます。さらに,結合列にインデクスが定義してあれば,結合にインデクスを使用できるため,入出力回数を削減できます。

(d) 例

ORは更にIN述語に変換した方がよい場合があります。詳細については,「探索条件にORを指定した検索(その2)」を参照してください。

  • 1表検索の場合

    C1にインデクス定義
    SELECT * FROM T1 WHERE (C1=10 AND C2=20) OR (C1=10 AND C2=30)
                 ↓
    SELECT * FROM T1 WHERE C1=10 AND (C2=20 OR C2=30)

    ただし,C1=10が十分に絞り込めないで,(C1,C2)に複数列インデクスを定義する場合には,C1=10を抜き出さないほうが性能が良い場合があります。

  • 結合検索の場合

    SELECT * FROM T1, T2 
        WHERE (T1.C1=T2.C1 AND T1.C2=10) OR (T1.C1=T2.C1 AND T2.C2=20)
                  ↓
    SELECT * FROM T1, T2 WHERE T1.C1=T2.C1 AND (T1.C2=10 OR T2.C2=20)

(2) 探索条件にORを指定した検索(その2)

(a) 表示の確認

探索条件に対して同一列に対する条件をORで指定している場合に,サーチ条件がない,又はサーチ条件が有効でなくインデクスのサーチ範囲が絞れずに性能が悪くないか確認してください。

(b) ベターユース

HiRDBのバージョン06-02以降の場合,HiRDBのバージョンが06-01よりも前で単一列インデクスが定義されている場合,及びHiRDBのバージョンが06-01よりも前で複数列インデクスが定義されている場合とでベターユースが異なります。

  • HiRDBのバージョンが06-02以降の場合

    OR演算の両辺に,同じ列に対する=述語を指定し,かつインデクスが定義されている場合には,IN述語を使用してください。

  • HiRDBのバージョンが06-01よりも前で単一列インデクスが定義されている場合

    OR演算の両辺に,同じ列に対する=述語を指定し,かつ列に単一列インデクスが定義されている場合には,IN述語を使用してください。

  • HiRDBのバージョンが06-01よりも前で複数列インデクスが定義されている場合

    複数列インデクスの第1構成列に定義した列に,IN述語を指定している場合には,OR演算を使用してください。

(c) 理由

  • HiRDBのバージョンが06-02以降の場合

    単一列インデクス,及び複数列インデクスは,IN述語内の値指定ごとにインデクスをサーチするため(サーチ条件種別のATS,RANGES),インデクスのサーチ範囲を絞り込めます。そのため,CPU時間,及び入出力回数を削減できます。

  • HiRDBのバージョンが06-01よりも前で単一列インデクスが定義されている場合

    単一列インデクスの場合には,IN述語内の値指定ごとにインデクスをサーチするため(サーチ条件種別のATS),インデクスのサーチ範囲を絞り込めます。そのため,CPU時間,及び入出力回数を削減できます。

  • HiRDBのバージョンが06-01よりも前で複数列インデクスが定義されている場合

    複数列インデクスの場合には,IN述語内の値指定の最小値から最大値までサーチするため(ただし,値指定に定数以外が含まれる場合にはすべてのリーフページを参照します),インデクスのサーチ範囲が広くなります。

    OR演算子に変換すると,Scan TypeがOR PLURAL INDEXES SCANとなる場合があります。この場合,OR演算子の左辺と右辺で別々にインデクスをサーチするので,インデクスのサーチ範囲を絞り込めるため,入出力時間を削減できます。

(d) 例

  • T1(C1)に単一列インデクス,又はT1(C1,C2)に複数列インデクスが定義されている場合(HiRDBのバージョンが06-02以降のとき)

    SELECT * FROM T1 WHERE C1=10 OR C1=20
               ↓
    SELECT * FROM T1 WHERE C1 IN (10,20)
  • T1(C1)に単一列インデクスが定義されている場合(HiRDBのバージョンは06-01よりも前のとき)

    SELECT * FROM T1 WHERE C1=10 OR C1=20
               ↓
    SELECT * FROM T1 WHERE C1 IN (10,20)
  • T1(C1,C2)に複数列インデクス(C1が第1構成列であること)が定義されている場合(HiRDBのバージョンは06-01よりも前のとき)

    SELECT * FROM T1 WHERE C1 IN (10,20)
               ↓
    SELECT * FROM T1 WHERE C1=10 OR C1=20

(e) 注意事項

HiRDBのバージョンが06-01よりも前の複数列インデクスの場合でも,次の二つの条件を共に満たすときには,IN述語を使用してください。

  • IN述語内の値指定が定数だけである。

  • IN述語内の値指定の最小値から最大値までのキー値数が少ない。

(3) 結合条件にORを指定した結合検索

(a) 表示の確認

Join TypeがCROSS JOINとなっている場合,内部的に直積処理をしています。結合条件にOR演算子を指定している場合,ORの両辺を別々に指定した集合演算(UNION,又はUNION ALL)を用いた等価なSQLにすると,効率的に検索できる可能性があります。

(b) ベターユース

結合条件がORで結ばれている場合は,ORの両辺を別々に指定した集合演算を使用します。

  • 選択式にDISTINCTを指定している場合

    UNIONを使用します。

  • 選択式にDISTINCTを指定していない場合

    UNION ALLを使用します。

(c) 理由

結合条件をOR演算子で結んでいる場合,結合する表の直積をしてから,直積結果に対して結合条件を評価します。

OR演算子を分離すると,ネストループジョイン,又はマージジョインをするので,結合時のデータの突き合わせ回数を削減できます。

さらに,ネストループジョインをすると,結合にインデクスを使用できるので,入出力回数を削減できます。

(d) 例

  • DISTINCT指定ありの場合

    SELECT DISTINCT * FROM T1, T2 
        WHERE (T1.C1=T2.C1 OR T1.C2=T2.C2) AND T1.C3=10
                ↓
    SELECT * FROM T1, T2 WHERE T1.C1=T2.C1 AND T1.C3=10
      UNION
    SELECT * FROM T1, T2 WHERE T1.C2=T2.C2 AND T1.C3=10
  • DISTINCT指定なしの場合

    SELECT * FROM T1, T2 WHERE (T1.C1=T2.C1 OR T1.C2=T2.C2) AND T1.C3=10
                ↓
    SELECT * FROM T1, T2 WHERE T1.C1=T2.C1 AND T1.C3=10
      UNION ALL
    SELECT * FROM T1, T2 WHERE T1.C2=T2.C2 
        AND (T1.C1<>T2.C1 OR T1.C1 IS NULL OR T2.C1 IS NULL) AND T1.C3=10

(e) 注意事項

  1. UNIONを指定すると,内部的に各問合せ指定の結果の作業表を作成します。この場合,重複排除のためにソート処理をします。

    また,UNION ALLを指定した場合も,内部的に各問合せ指定の結果の作業表を作成します。ただし,この場合はソート処理をしません。

  2. 結合列にインデクスが定義されていても,外側表が制限条件で絞り込まれていなければ,結合にインデクスを使用しません。結合列にインデクスが定義されている表が内側表になり,もう一方の表が外側表になります。

  3. 「(d) 例」のDISTINCT指定なしの場合の例は,T1.C1,T2.C1がNOT NULL 列,又はNULL値を挿入しない運用であれば,IS NULL述語は必要ありません。また,選択式にDISTINCTを指定しても意図した結果を得られる場合は,集合演算をUNION ALLではなくUNIONにするようにしてください。

(4) 範囲述語の検索

(a) ベターユース

AND演算で同じ列の>=述語と<=述語を結んでいる場合,SQL最適化処理をする前にBETWEEN述語に変換します。この場合,WHERE句の先に指定した述語から順に,BETWEEN述語に変換していきます。

AND演算で同じ列の>=述語と<=述語を結んだ条件とBETWEEN述語は,HiRDBの内部では等価に扱われるため,どちらで指定しても同じになります。

>=述語と<=述語が範囲を形成しているかどうか確認してください。

(b) 例

  • 次の二つのSQL文は同じアクセスパスを選択します

    SELECT * FROM T1 WHERE C1 BETWEEN 10 AND 20
    SELECT * FROM T1 WHERE C1>=10 AND C1 <= 20
  • HiRDBは内部的に次のような変換をします

    SELECT * FROM T1 WHERE C1<=50 AND C1>=20 AND C1<=30
                  ↓
    SELECT * FROM T1 WHERE C1 BETWEEN 20 AND 50 AND C1<=30

(c) 注意事項

冗長な述語がある場合,データベースアクセス時に不要な条件判定がされます。冗長な条件はできるだけ削除するようにしてください。

(5) GROUP BY指定した検索

(a) ベターユース

HiRDB/パラレルサーバで複数の列に対するGROUP BY検索をする場合は,重複の少ないGROUP化列をGROUP BY句の先に指定してください。ただし,SQL最適化オプションに1024を指定していない場合だけです。

(b) 理由

HiRDB/パラレルサーバで複数のフロータブルサーバを使用してGROUP BY処理をする場合に,フロータブルサーバへデータを振り分けるためにGROUP BY句の先頭の列でハッシングしています。GROUP BY句の先頭の列に重複が少ない場合,各フロータブルサーバへ均等にハッシングできるので,並列処理の効果が上がります。

(c) 例

SELECT C1,C2,SUM(C3) FROM T1 GROUP BY C1,C2

(C1の重複数)>(C2の重複数)の場合は次のように変更します。

         ↓
SELECT C1,C2,SUM(C3) FROM T1 GROUP BY C2,C1

(d) 注意事項

SQL最適化オプションに1024を指定している場合には,すべてのグループ化列を使用してハッシングするので,GROUP BYの順番を入れ替える必要はありません。ただし,「ORDER BY,GROUP BYを指定した検索に使用する表のインデクス定義」に該当する場合には,グループ化列を入れ替えないでください。

(6) GROUP BY,ORDER BYの両方を指定した検索

(a) ベターユース

  • すべてのGROUP BY列を構成列に含むインデクスがある場合(HiRDB/シングルサーバの場合)

    GROUP BY列をインデクス構成列順に指定します。

  • すべてのGROUP BY列を構成列に含むインデクスがない場合

    ORDER BY,GROUP BYを両方指定した検索で,ORDER BY列がGROUP BY列にすべて含まれるときは,ORDER BY列の指定順にGROUP BY列を指定してください。

(b) 理由

  • すべてのGROUP BY列を構成列に含むインデクスがある場合(HiRDB/シングルサーバの場合)

    GROUP BY処理のためのソート処理を省略できます。この場合,ORDER BY処理のためのソート処理はされるが,グループ化処理後のデータ(データ件数が少ない)に対してソート処理をするため,検索性能が良くなります。

  • すべてのGROUP BY列を構成列に含むインデクスがない場合

    GROUP BY句とORDER BY句の列指定の順が同じ場合,ORDER BYのためのソート処理を省略できます。

(c) 例

  • すべてのGROUP BY列を構成列に含むインデクスがある場合(HiRDB/シングルサーバ)

    インデクス T1(C2, C1)
    SELECT C1,C2,SUM(C3) FROM T1 GROUP BY C1,C2 ORDER BY C1,C2
               ↓
    SELECT C1,C2,SUM(C3) FROM T1 GROUP BY C2,C1 ORDER BY C1,C2
  • すべてのGROUP BY列を構成列に含むインデクスがない場合

    SELECT C1,C2,SUM(C3) FROM T1 GROUP BY C1,C2 ORDER BY C2,C1
               ↓
    SELECT C1,C2,SUM(C3) FROM T1 GROUP BY C2,C1 ORDER BY C2,C1
     
    SELECT C1,C2,SUM(C3) FROM T1 GROUP BY C1,C2 ORDER BY C2 DESC
               ↓
    SELECT C1,C2,SUM(C3) FROM T1 GROUP BY C2,C1 ORDER BY C2 DESC

(d) 注意事項

GROUP BY句に対して,「ORDER BY,GROUP BYを指定した検索に使用する表のインデクス定義」に該当するインデクスを定義できる場合,そちらを優先してください。