実行計画の処理について、個人的に一番助かっているのはJulian Dyke氏の一覧です。しかし、ここでは別の方法で説明していきます。
インデックスとテーブルへのアクセス
- INDEX UNIQUE SCAN
INDEX UNIQUE SCAN
は、 Bツリーの走査のみを行います。データベースは、一意制約により 検索条件が1件にしか一致しない事が確実な場合に、これを使います。第1章1, 「 SQLインデックスの内部構造」も参照して下さい。- INDEX RANGE SCAN
INDEX RANGE SCAN
は、Bツリーの走査に 加えて、一致するエントリを探すのにリーフノードチェーンをたどります。第1章1, 「 SQLインデックスの内部構造」も参照して下さい。フィルタ述語は、
INDEX RANGE SCAN
の パフォーマンス上の問題の原因になる事があります。次の節で、 どのようにそれを見分けるかを説明します。- INDEX FULL SCAN
インデックスの全体つまり全行を、インデックスの順番に沿って読みます。様々なシステム統計情報に基づき、 インデックスの順序に沿って全行が必要と判断した時、データベースはこの処理を実行します。例えば、対応する
order by
句がある時などです。なお オプティマイザは、INDEX FAST FULL SCAN
を代わりに使い、 追加でソート処理を行う事もあります。第6章6, 「ソートとグルーピング」も参照して下さい。- INDEX FAST FULL SCAN
インデックスの全体つまり全行を、ディスクに保存されている通りに 読みます。この処理は、必要な列が全てインデックス上にある場合にフルテーブルスキャンの代わりに実行されるのが一般的です。
TABLE ACCESS FULL
と同じくINDEX FAST FULL SCAN
も、複数ブロックの読み取り処理に利点があります。第5章5, 「データのクラスタリング: インデックスの強力さの2つ目」も参照して下さい。- TABLE ACCESS BY INDEX ROWID
前段のインデックス検索で取得した
ROWID
を使って、 テーブルから行を取り出します。第1章1, 「 SQLインデックスの内部構造」も参照して下さい。- TABLE ACCESS FULL
フルテーブルスキャンとして知られる処理です。テーブル全体つまり全行・全列をディスクに保存されている通りに 読みます。複数ブロックの読み出し処理により、フルテーブルスキャンの 速度は大幅に改善されはしますが、最も重い処理の1つである事に 変わりありません。IO処理も多いですが、フルテーブルスキャンでは全てのテーブルの行の値をチェックしなければならないので、 かなりのCPU時間も消費します。「フルテーブルスキャン」も参照して下さい。
協力してください
この記事が気に入ったら、私の書いた本「SQLパフォーマンス詳解」や私によるトレーニングもきっと気にいるはず。
結合
通常、結合処理で同時に処理できるのは 2テーブルまでです。1つのクエリにそれ以上の結合対象のテーブルがある場合、まず2つのテーブルを結合し、それからその中間結果を次のテーブルと 結合するというように、順番に処理されます。結合の話をする場合には、 「テーブル」という言葉は「中間結果」の事を指す場合もあるのです。
- NESTED LOOPS JOIN
片方のテーブルから結果を取り出し、その結果をもう1つの テーブルの各行に対して問い合わせて、2つのテーブルを結合します。「入れ子ループ」も参照して下さい。
- HASH JOIN
ハッシュ結合では、結合の片方から候補となるレコードをハッシュテーブルにロードし、それを結合のもう片方の各行と 突き合わせます。「ハッシュ結合」も参照して下さい。
- MERGE JOIN
マージ結合は、並べ替えられた2つのリストをジッパーのように マージします。結合の両辺は事前にソートしておく必要があります。「ソートマージ」も参照して下さい。
ソートとグルーピング
- SORT ORDER BY
order by
句に従って、結果をソートします。この処理は、中間結果(パイプライン化されていないもの)を マテリアライズするために、非常に多くのメモリを必要とします。「インデックスを使ったorder by」も参照して下さい。- SORT ORDER BY STOPKEY
order by
句に従って、結果セットの一部をソートします。パイプライン化された実行ができない場合は、 最初のN件のみを選択するクエリとして実行します。「最初のN行のみの選択」も参照して下さい。- SORT GROUP BY
group by
列の結果セットをソートし、 次のステップで並べ替えられた結果をまとめます。この処理は、中間結果(パイプライン化されていないもの)を マテリアライズするために、非常に多くのメモリを必要とします。「インデックスを使ったgroup by」も参照して下さい。- SORT GROUP BY NOSORT
group by
句に従って、並べ替え済みの 結果セットをまとめます。この処理は中間結果をバッファせず、パイプライン化して実行します。「インデックスを使ったgroup by」も参照して下さい。- HASH GROUP BY
ハッシュテーブルを使って結果をグルーピングします。この処理は、中間結果(パイプライン化されていないもの)を マテリアライズするために、非常に多くのメモリを必要とします。 出力は、一定のルールに沿って並べられているわけではないものになります。「インデックスを使ったgroup by」も参照して下さい。
最初のN件のみを選択するクエリ
最初のN件のみを選択するクエリの効率は、内部で動作する処理の実行モードに依存します。SORT ORDER BY
のような、パイプライン化されていない処理を途中で中断する動作の時は、非常に非効率になります。
- COUNT STOPKEY
必要な行数が取り出せた時点で、内部的な処理を中断します。「最初のN行のみの選択」も参照して下さい。
- WINDOW NOSORT STOPKEY
必要な行数が取り出せた時点で実行を中断するために、窓関数(
over
句)を使います。「効率的なページネーションのための窓関数の使用」も参照して下さい。