【Oracle】インデックス設定が上手くいかない時の対処法

•DBにインデックス設定したのに、実行計画でインデックスが効いていない

•検索が遅い

上記悩みに対しての対処方法の備忘録です。

はじめに:自己紹介

20卒・社会3年目のSEです。

理系工学部出身です。

SEとして、仕様書作成〜開発、テスト、本番環境移行までを複数回経験しており、今年からチームリーダーとして進捗管理を行なっています。

インデックスとは

インデックスとはDBから検索する時に、検索条件に応じて検索速度を上げてくれるものです。

インデックスの反映方法

インデックス設定をしても、その設定が反映されていない場合があります。

•元々DBにデータが入っている状態でインデックス設定した

•インデックス設定をした時からDBデータがかなり変わった

上記の場合は、以下を実行してインデックスを反映させる必要があります。

インデックスの分析を行い、設定をしてくれます。

analyze table テーブル名 compute statistics;

インデックスが効かない条件

インデックスの反映設定をしても、統計情報でインデックスが効かない場合があります。

その条件について解説します。

①インデックススキャンよりもフルスキャンの方が早い

条件によってはフルスキャンの方が速度が早い、変わらない場合があります。

以下参考値(データ構成によって異なる)

✔︎検索条件に合致するものが、DB全体の約10%以上の場合はフルスキャンと速度が変わらないのでインデックスを作成しない

✔︎5%〜10%の場合は、検索速度向上とインデックス更新時の速度低下のバランスを考慮し、インデックス作成をするか判断

✔︎5%未満の場合はインデックス作成による検索向上のメリットが大きいのでインデックス作成をする

②インデックスを用いた検索で、特定の条件が使用されている場合

以下の場合は、インデックス設定されていても使用されません。以下は使用しないことが必要です。

✔︎インデックスに対して「NULL」や「NOT」が使用されている場合

✔︎条件式に関数や計算を使用している場合

✔︎「LIKE」条件の中間一致•後方一致を使用している場合

③適切な実行計画が選択されていない

データの偏りなどにより、適正な実行計画が選択されていない可能性があります。

以下対処方法で特定のインデックス(もしくはフルスキャン)を使用するように指定することができます。

select文直後にインデックス指定文言を追加

✔︎フルスキャンを指定する場合

「SELECT /*+ FULL(emp)*/ name from•••」

✔︎特定のインデックスを指定する場合

例 : name_indexの使用を指定する時

「SELECT /*+ INDEX(name_index) */ name from•••」

注意点として、

指定した場合は実行計画が固定されてしまうので、定期的な見直しが必要です。

最適な実行計画は、データ件数や値によって変わってくるため。

④インデックスがメンテナンスされていない

適切なインデックスを設定したとしても、データが変わってくるとメンテナンスが必要になります。

具体的には

大量にデータを追加、削除した場合

に必要です。

インデックス再構築方法

以下コマンドを実行することで、インデックス再構築できます。

「ALTER INDEX 索引名 REBUILD;」

⑤インデックスの順番が、絞り込み条件の順番と合っていない

インデックスの順番が、実際に検索しているSQLの絞り込み条件と一致していない場合は、インデックスが効かないです。順番を一致させる必要があります。

まとめ

インデックスがうまく設定されない要因には下記があります。

①インデックススキャンよりもフルスキャンの方が早い。

②インデックスを用いた検索で、特定の条件が使用されている場合

③適切な実行計画が選択されていない

④インデックスがメンテナンスされていない

データ構造に応じて適切なインデックスが設定できれば効率が上がります。そのためには、データ構造や実行計画を定期的に見直して、試行錯誤が必要です。

以上、参考になれば幸いです。