まずは今回の検証に利用するテーブルを紹介。
create table atl.HOGE (
PK number(10) NOT NULL,
FOO varchar2(512) NOT NULL,
BAR varchar2(512) NOT NULL,
BAZ varchar2(512) NOT NULL,
CONSTRAINT PK_HOGE PRIMARY KEY(PK)
) tablespace ATL_SPACE;
データは100万件ほど格納してます。
このテーブル(PKにしかインデックスは張られていない)で、次のSQL文を実行すると・・・・
select PK from HOGE where FOO like '%aaa%';
実行結果
SELECT STATEMENT Cost = 57095
TABLE ACCESS FULL HOGE
23276ms
とまぁこんな結果。
23秒です。
100万件にテーブルフルスキャンがかかっているので、こんなものでしょう。遅いです。
このテーブルを高速化してみたいと思います。
まずは
誤りの事例からご紹介。
インデックスを張ってみましょう。
CREATE INDEX IDX_HOGE1 ON
atl.HOGE (FOO)
TABLESPACE ATL_SPACE;
この状態で同じSQL文を実行した時の
実行結果は次の通り。
SELECT STATEMENT Cost = 57095
TABLE ACCESS FULL HOGE
22776ms
・・・遅いです。速くなってないですねー。実行計画も変わってません。
ダメなインデックスの張り方ですね。
次はインデックスが(多少なりとも)効くように複合インデックスを張ってみます。
(IDX_HOGE1は別途削除してます)
CREATE INDEX IDX_HOGE2 ON
atl.HOGE (FOO,PK)
TABLESPACE ATL_SPACE
この状態で同じSQL文を実行した時の
実行結果は次の通り。
SELECT STATEMENT Cost = 19056
INDEX FAST FULL SCAN IDX_HOGE2
10421ms
多少速くなってますね。
10秒まで速くなりました。
これでも遅いですが、前述のものよりはましでしょう^^;
実行計画を見ても、
テーブルフルスキャンから
インデックスフルスキャンに変わってます。
ポイントは、
FOOと
PKに張った
複合インデックスですね。
実行したSQLは、FOOで部分一致して、PKのデータを取得しています。
テーブルにアクセスしないために、複合インデックスを張ってインデックスからのスキャンとしています。
ただこの方法だとWhere句の絞りこみカラムと、Select句のカラムを全て複合インデックスに
しないといけないから、まぁ巨大なインデックスになっていくんですけどねぇ^^;
というわけでATLの部分一致考察でした。
紹介した方法以外で、部分一致の高速化は、
・oracle text
くらいでしょうか。
まぁ後はSQL全体を見直して、絞り込んでから部分一致させると速くなりますが。