実行計画の処理


この節では、MicrosoftのSQL Serverにおける 最も良く現われる実行計画の処理を説明します。Microsoftの ドキュメントも参照して下さい。

インデックスとテーブルへのアクセス

SQL Serverの用語はシンプルになっています。 「Scan」はインデックス全体を読み込み、「Seek」はインデックスあるいは テーブルの指定された一部のみにアクセスするためにBツリーや 物理アドレス(RID、 Oracleで言うROWID)を使う処理になっています。

Index Seek, Clustered Index Seek

Index Seekは、Bツリーの走査に 加えて、一致するエントリを探すのに リーフノードチェーンをたどります。第1章, 「 SQLインデックスの内部構造も参照して下さい。

Index Scan, Clustered Index Scan

インデックスの全体つまり全行を、インデックスの順番に 沿って読みます。様々なシステム統計情報に基づき、 インデックスの順序に沿って全行が必要と判断した時、 データベースはこの処理を実行します。例えば、対応する order by句がある時などです。

Key Lookup (Clustered)

クラスタ化インデックスから 1行を取り出します。これは、Oracleの索引構成表に対する INDEX UNIQUE SCANと同じです。データのクラスタリング: インデックスの強力さの2つ目も参照して下さい。

RID Lookup (Heap)

テーブルから1行を取り出します。 OracleのTABLE ACCESS BY INDEX ROWIDに当ります。 SQLインデックスの内部構造も参照して下さい。

Table Scan

フルテーブルスキャンとして知られる処理です。 テーブル全体つまり全行・全列をディスクに保存されている通りに 読みます。複数ブロックの読み出し処理により、Table Scanの 速度は大幅に改善されはしますが、最も重い処理の1つである事に 変わりありません。IO処理も多いですが、Table Scanでは 全てのテーブルの行の値をチェックしなければならないので、 かなりのCPU時間も消費します。「フルテーブルスキャン」も参照して下さい。

このウェブサイトにぴったりのカップは僕たちのショップにあります。
#見た目もいい感じだし、ここでの僕の仕事を支えてくれています

結合処理

通常、結合処理で同時に処理できるのは2テーブルまでです。 1つのクエリにそれ以上の結合対象のテーブルがある場合、 まず2つのテーブルを結合し、それからその中間結果を次のテーブルと 結合するというように、順番に処理されます。結合の話をする場合には、 「テーブル」という言葉は「中間結果」の事を指す場合もあるのです。

Nested Loops

片方のテーブルから結果を取り出し、その結果をもう1つの テーブルの各行に対して問い合わせて、2つのテーブルを結合します。 SQL Serverでは、インデックスアクセスの後にテーブルデータを取り出すのにも 入れ子のループ処理を使います。「入れ子ループ」も参照して下さい。

Hash Match

ハッシュマッチ結合では、 結合の片方から候補となるレコードをハッシュテーブルにロードし、 それを結合のもう片方の各行と突き合わせます。 「ハッシュ結合」も参照して下さい。

Merge Join

マージ結合は、 並べ替えられた2つのリストをジッパーのようにマージします。 結合の両辺は事前にソートしておく必要があります。 「ソートマージ」も参照して下さい。

ソートとグルーピング

Sort

order by句に従って、 結果をソートします。この処理は、 中間結果(パイプライン化されていないもの)をマテリアライズするために、 非常に多くのメモリを必要とします。「インデックスを使ったorder by」も参照して下さい。

Sort (Top N Sort)

order by句に従って、 結果セットの一部をソートします。 パイプライン化された実行ができない場合は、 最初のN件のみを選択するクエリとして実行します。 「最初のN行のみの選択」も参照して下さい。

Stream Aggregate

group by句に従って、 並べ替え済みの結果セットをまとめます。この処理は中間結果をバッファせず、 パイプライン化して実行します。「インデックスを使ったgroup by」も参照して下さい。

Hash Match (Aggregate)

レコードをグルーピングするのに一時的なハッシュテーブルを使います。 この処理では、データセットは事前にソートされている必要はありませんが、 中間結果(パイプライン化されていないもの)をマテリアライズするために 非常に多くのメモリを必要とします。出力は、 一定のルールに沿って並べられているわけではないものになります。 「インデックスを使ったgroup by」も参照して下さい。

最初のN件のみを選択するクエリ

Top

必要な行数が取り出せた時点で、内部的な処理を中断します。 「最初のN行のみの選択」も参照して下さい。

最初のN件のみを選択するクエリの効率は、 内部で動作する処理の実行モードに依存します。Sortのような、 パイプライン化されていない処理を途中で中断する動作の時は、 非常に非効率になります。

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