Oracleはwhere
句(述語)を適用するのに、
3つの方法を使い分けます。
- アクセス述語 (「access」)
アクセス述語は、リーフノードの走査の開始と終了の条件を表しています。
- インデックスフィルタ述語 (インデックス操作に対する「filter」)
インデックスフィルタ述語は、リーフノード走査の時にのみ適用されます。スキャンされる範囲の開始と終了の条件を表したり、 範囲を狭めるものとしては使われません。
- テーブルレベルのフィルタ述語 (テーブル操作に対する「filter」)
インデックスの一部でない列に対する述語は、テーブルのレベルで評価されます。その場合データベースは、 まずテーブルから行をロードしなければなりません。
注記
インデックスフィルタ述語は、間違った安心感を持ってしまう原因になりかねません。 インデックスは確かに使われますが、データ量やシステムの負荷が増大すると、 急激にパフォーマンス劣化が起きる可能性があります。
DBMS_XPLAN
ユーティリティ(「実行計画の表示方法」を参照)を使って生成された実行計画は、
以下のような実行計画の表の「Predicate Information」セクションで、インデックスの使用状況について表示します。
------------------------------------------------------
| Id | Operation | Name | Rows | Cost |
------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1445 |
| 1 | SORT AGGREGATE | | 1 | |
|* 2 | INDEX RANGE SCAN| SCALE_SLOW | 4485 | 1445 |
------------------------------------------------------
Predicate Information (identified by operation id):
2 - access("SECTION"=:A AND "ID2"=:B)
filter("ID2"=:B)
述語情報の番号は、実行計画の「Id」列に対応しています。 見ての通り、述語情報のある処理にはアスタリスクマークが付いています。
協力してください
この記事が気に入ったら、私の書いた本「SQLパフォーマンス詳解」や私によるトレーニングもきっと気にいるはず。
パフォーマンスとスケーラビリティの
章から抜粋したこの例では、INDEX RANGE SCAN
がアクセス述語と
フィルタ述語を持っていると表示されています。Oracleは、フィルタ述語をアクセス述語としても表示する特徴があります。この実行計画にある
ID2=:B
がその例です。
重要
条件がフィルタ述語として表示されていれば、それはフィルタ述語です。アクセス述語と表示されていても関係ありません。
従ってこの例でINDEX RANGE SCAN
は、
"SECTION"=:A
の条件の範囲全体をスキャンし、
各行に対して"ID2"=:B
のフィルタを適用します。
テーブルレベルでのフィルタ述語は、TABLE ACCESS BY INDEX ROWID
や
TABLE ACCESS FULL
と言った対応するテーブルアクセスに対して表示されます。
ツールが違えば述語情報も違って表示される事に注意しましょう。例えば、Oracle SQL Developerでは述語情報を以下のように対応する処理の下に表示します。
図A.1Oracle SQL Developerにおけるアクセス述語とフィルタ述語

ツールによっては述語情報を表示してくれないものもあります。「実行計画の表示方法」で説明した
DBMS_XPLAN
に立ち返るようにしましょう。
ヒント
「大なり、小なり、
BETWEEN
」の節では、例を挙げて アクセス述語とフィルタ述語の違いを説明しています。第3章3, 「パフォーマンスとスケーラビリティ」では、アクセス述語と インデックスフィルタ述語のパフォーマンスの違いを説明しています。