この章では、SQL Serverがクライアントからのクエリを受け取ってから、データにアクセスするまでの内部的なステップを紹介します。クエリが実行されるまでの一連の処理の流れや、その過程で決定されるデータアクセス方法は、クエリ実行時のパフォーマンスに大きな影響を与えます。そのため、数多く存在するSQL Serverのコンポーネントの中でも特に重要な部分だと言えます。この処理を行うコンポーネント群を総称して、リレーショナルエンジンもしくはクエリプロセッサと呼んでいます。リレーショナルエンジンの動作を理解することによって、パフォーマンス関連のトラブルシューティングを行う際に、様々な事象の中から重要な問題点を絞り込むことが可能になります。
8.1 リレーショナルエンジンの構成
リレーショナルエンジンは、大きく分けて次の3つのコンポーネントで構成されています。それぞれのコンポーネントは、さらに数多くのサブコンポーネントによって構成されています(図8.1)。
8.2 クエリのライフサイクル
クライアントから受け取ったクエリの処理要求は、リレーショナルエンジン内で図8.2のようなステップを経て実行されます。
①プランキャッシュの確認
プランキャッシュ(あるいはプロシージャキャッシュ)には、これまでに実行されたクエリの実行プランが一定期間格納されています。また、格納されたクエリ実行プランは、クエリ実行プラン生成のもととなった実際のクエリテキスト(SELECTステートメントなど)も保持しています。
もしも、クライアントから受け取ったクエリが、すでにプランキャッシュに存在するクエリと合致する場合は、多大なコストを必要とする最適化などの処理を省くことができます。そのため、クライアントからクエリを受け取ったら、まずプランキャッシュに合致するものが存在するかを、クエリテキストの比較によって確認します。
②解析(Parsing)
クライアントから受け取ったクエリの解析を行います。クエリの解析とは、クエリの構成要素を入力データソースとしてのテーブルや、入力データのフィルタリングとしてのWHERE句、データの処理に影響を与えるORDER BYオペレータ[※1]などにいったん分類し、それらをツリー構造に再構成することを意味します。再構成されたツリーはクエリツリー(またはリレーショナルオペレータツリー)と呼ばれ、その後のステップでクエリの最適化が行われる際に使用されます(図8.3)。
※1 結果セットを任意の列で並べ替える際に使用するオペレータです。
③クエリのパラメータ化
将来的にクエリが再実行されることに備えて、プランキャッシュに格納するための準備を行います。具体的には、クライアントから受け取ったクエリテキストをパラメータ化クエリに変換します(図8.4)。
④バインド
クエリで操作されるテーブルなどの列と、クライアントへ返される結果セットのバインド(関連付け)が行われます。
⑤最適化
クエリの解析結果として受け渡されたクエリツリーをもとに、クエリオプティマイザによってクエリ実行プランが生成されます。クエリオプティマイザの動作は、パフォーマンスチューニングの際にとても重要な意味を持つため、次節で詳細を説明します。
⑥クエリ実行プラン生成(もしくは再利用)
クエリ実行プランがプランキャッシュに存在する場合は、再利用が行われます。存在しない場合は、クエリオプティマイザによって生成されたコンパイル済みプランをもとに実行可能プランが生成されます。
⑦リソース確保
クエリ実行プランに基づいて、クエリを処理するために必要なリソースを確保します。たとえば、結果セットの並べ替えが必要な場合は、並べ替え用のメモリの獲得を要求します。あるいは、並列で処理されるべきクエリには、並列処理に必要な内部スレッドの獲得要求を行います。
⑧実行
クエリ実行プランに基づいたリソースの確保が完了すると、クエリの実行が開始されます。
⑨クエリ実行プランの登録
クエリ実行プランがプランキャッシュに存在しない場合は登録します。