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


SQL Serverは、where句(述語)を適用するのに、 3つの方法を使い分けます。

アクセス述語 (「Seek Predicates」)

アクセス述語は、リーフノードの走査の開始と終了の条件を 表しています。

インデックスフィルタ述語 (インデックス操作に対する「Predicates」 または 「where」)

インデックスフィルタ述語は、リーフノード走査の時にのみ適用されます。 スキャンされる範囲の開始と終了の条件を表したり、 範囲を狭めるものとしては使われません。

テーブルレベルのフィルタ述語 (テーブル操作に対する「where」)

インデックスの一部でない列に対する述語は、 テーブルのレベルで評価されます。その場合データベースは、 まずテーブルから行をロードしなければなりません。

この節では、SQL Serverの実行計画から フィルタ述語を見つける方法について説明します。第3章フィルタ述語の 影響について説明したサンプルを使います。付録に、テーブルやデータを生成するスクリプトがあります。

CREATE TABLE scale_data (
   section NUMERIC NOT NULL,
   id1     NUMERIC NOT NULL,
   id2     NUMERIC NOT NULL
);
CREATE INDEX scale_slow ON scale_data(section, id1, id2);

例文では、SECTIONID2で選択しています。

SELECT count(*)
  FROM scale_data
 WHERE section = @sec
   AND id2 = @id2

グラフィカルな形式での実行計画

グラフィカルな実行計画では、マウスをIndex Seekの 処理の上に持って来た時だけ表示されるツールチップ内に述語情報は 隠れてしまっています。述語情報を見るには、 このページの図のように、Index Seekアイコンの上に マウスを動かす必要があります。

SQL ServerのSeek Predicatesは、 Oracleのアクセス述語に当たるもので、リーフノードの走査範囲を狭めます。 フィルタ述語はSQL Serverのグラフィカルな形式の実行計画では、 単にPredicatesとだけラベルされます。

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

テーブル形式での実行計画

テーブル形式での実行計画では、処理が書かれたのと同じ列に 述語情報が表示されます。一度に関連する情報を全てコピーアンドペーストするのに 便利です。

DECLARE @sec numeric;
DECLARE @id2 numeric;
SET STATISTICS PROFILE ON;
SELECT count(*)
  FROM scale_data
 WHERE section = @sec
   AND id2 = @id2;
SET STATISTICS PROFILE OFF;

実行計画は、結果ペインの2番目の結果セットとして表示されます。 読みやすさのために少しだけフォーマットを変えてありますが、 次の例はStmtText列の内容を表しています。

|--Compute Scalar(DEFINE:([Expr1004]=CONVERT_IMPLICIT(...))
     |--Stream Aggregate(DEFINE:([Expr1008]=Count(*)))
          |--Index Seek(OBJECT:([scale_data].[scale_slow]),
             SEEK: ([scale_data].[section]=[@sec])
                    ORDERED FORWARD
             WHERE:([scale_data].[id2]=[@id2]))

SEEKラベルがアクセス述語である事を表し、 WHEREラベルがフィルタ述語を表しています。

ヒント

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