アクセス述語とフィルタ述語の見分け方


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」列に対応しています。 見ての通り、述語情報のある処理にはアスタリスクマークが付いています。

初心者からエキスパートまで役に立つ内容です。
特に駆け出しのエンジニアは持っておくといい

パフォーマンスとスケーラビリティの 章から抜粋したこの例では、INDEX RANGE SCANがアクセス述語と フィルタ述語を持っていると表示されています。Oracleは、フィルタ述語を アクセス述語としても表示する特徴があります。この実行計画にある ID2=:Bがその例です。

重要

条件がフィルタ述語として表示されていれば、それはフィルタ述語です。 アクセス述語と表示されていても関係ありません。

従ってこの例でINDEX RANGE SCANは、 "SECTION"=:Aの条件の範囲全体をスキャンし、 各行に対して"ID2"=:Bのフィルタを適用します。

テーブルレベルでのフィルタ述語は、TABLE ACCESS BY INDEX ROWIDTABLE ACCESS FULLと言った対応するテーブルアクセスに対して 表示されます。

ツールが違えば述語情報も違って表示される事に注意しましょう。 例えば、Oracle SQL Developerでは述語情報を以下のように対応する処理の下に 表示します。

図A.1 Oracle SQL Developerにおけるアクセス述語とフィルタ述語


ツールによっては述語情報を表示してくれないものもあります。 「実行計画の表示方法」で説明した DBMS_XPLANに立ち返るようにしましょう。

Photo of Markus Winand
Markus Winand氏は、開発者がSQLパフォーマンスを改善するお手伝いをしています。 彼は、SQL Performance Explainedの 著者でもあり、出張トレーニングhttp://winand.at/での リモート講義も 行っています。