クエリ チューニングに関する推奨設定
クエリの中には、他のクエリよりも多くのリソースを消費するものがあります。たとえば、大きな結果セットを返すクエリや一意でない WHERE 句を含むクエリは、常にリソースを大きく消費します。このようなコンストラクトについては、クエリ オプティマイザのインテリジェント機能を使用しても、単純なクエリのようにはリソース コストを回避することはできません。SQL Server では最適なアクセス プランが使用されますが、クエリの最適化には限度があります。
それでも次の操作を行うことで、クエリのパフォーマンス向上を図ることができます。
メモリを追加します。この解決策は、サーバーで多数の複雑なクエリを実行し、そのうちいくつかのクエリの実行速度が遅い場合に特に役立ちます。
複数のプロセッサを使用します。複数のプロセッサがあると、データベース エンジンで並列クエリを利用できるようになります。詳細については、「並列クエリ処理」を参照してください。
クエリを書き直します。このとき、次の点を考慮してください。
クエリにカーソルを使用している場合、より効率的な種類のカーソル (高速順方向専用カーソルなど) を使用するか、単一クエリを使用してカーソル クエリを記述できないかどうかを検討します。通常、単一クエリのパフォーマンスはカーソル操作を使用した場合を上回ります。一方、一連のカーソル ステートメントは外部ループ操作にするのが普通であり、内部ステートメントを使用して外部ループの各行を 1 回ずつ処理することになります。GROUP BY ステートメントまたは CASE ステートメントか、サブクエリで代用できないかどうかを検討してください。詳細については、「カーソルの種類 (データベース エンジン)」および「クエリの基礎」を参照してください。
アプリケーションでループを使用している場合、クエリ内にループを置くことを検討してください。アプリケーション内で、パラメータ化されたクエリを含んでいるループを使用していることがあります。この場合、クエリは何度も実行され、そのたびにアプリケーションを実行しているコンピュータと SQL Server との間でネットワーク ラウンド トリップを必要とします。これを回避するには、一時テーブルを使用して、単一の複雑なクエリを作成します。これにより、ネットワーク ラウンド トリップが 1 回で済みます。また、クエリ オプティマイザによる最適化の効率も、単一クエリの方が高くなります。詳細については、「Transact-SQL の手順」および「Transact-SQL 変数」を参照してください。
同じクエリ内で単一のテーブルに複数の別名を使用してインデックス積集合をシミュレートしないようにします。SQL Server では、インデックス積集合が自動的に考慮され、同一クエリ内の同一テーブルで複数のインデックスを利用できるので、この処理は不要になりました。次のサンプル クエリを見てみましょう。
SELECT * FROM lineitem WHERE partkey BETWEEN 17000 AND 17100 AND shipdate BETWEEN '1/1/1994' AND '1/31/1994'
SQL Server では、partkey 列と shipdate 列の両方でインデックスを使用し、2 つのサブセット間でハッシュ照合を実行してインデックス積集合を取得できます。
クエリのパラメータ化を使用して、キャッシュされたクエリ実行プランをの再利用を可能にします。複数のクエリでクエリ ハッシュおよびクエリ プラン ハッシュが同じである場合、パラメータ化されたクエリを 1 つ作成することでパフォーマンスを向上できます。リテラル値を指定して複数のクエリを呼び出す代わりに、1 つのクエリをパラメータを指定して呼び出すことで、キャッシュされたクエリ実行プランを再利用できます。詳細については、「クエリおよびクエリ プラン ハッシュを使用した類似クエリの検索およびチューニング」および「実行プランのキャッシュと再利用」を参照してください。
アプリケーションに変更を加えることができない場合は、強制パラメータ化を行うテンプレート プラン ガイドを使用することで、同様の結果を得ることができます。詳細については、「プラン ガイドを使用したクエリのパラメータ化動作の指定」を参照してください。
クエリ ヒントは必要な場合にだけ利用します。ヒントを使用して以前のバージョンの SQL Server に対して実行されたクエリは、ヒントを指定せずにテストする必要があります。ヒントを使用すると、クエリ オプティマイザで適切な実行プランを選択できないことがあります。詳細については、「SELECT (Transact-SQL)」を参照してください。
query_plan_hash を使用して、長期的にクエリのクエリ実行プランをキャプチャ、格納、および比較します。たとえば、システム構成を変更した後、ミッションクリティカルなクエリのクエリ プラン ハッシュ値を変更前のクエリ プラン ハッシュ値と比較できます。クエリ プラン ハッシュ値の相違から、システム構成の変更が原因で重要なクエリのクエリ実行プランが更新されたかどうかがわかります。また、sys.dm_exec_requests のクエリ プラン ハッシュがベースライン クエリ プラン ハッシュと異なる場合は、現在実行中の実行時間の長いクエリを停止することもできます。これにより、パフォーマンスが向上します。詳細については、「クエリおよびクエリ プラン ハッシュを使用した類似クエリの検索およびチューニング」を参照してください。
query governor 構成オプションを利用します。query governor 構成オプションを使用すると、実行時間の長いクエリによるシステム リソースの消費を防ぐことができます。既定では、実行時間に関係なくすべてのクエリの実行を許可するように設定されています。実行を許可する秒数の上限をクエリ ガバナに設定すると、全接続の全クエリ、または特定の接続のクエリについて、実行時間を制限できます。クエリ ガバナは実際の経過時間ではなく、推定クエリ コストに基づくため、実行時のオーバーヘッドはありません。また、実行時間の長いクエリは、あらかじめ定義された時間になるまで実行されるのではなく、開始する前に停止されます。詳細については、「query governor cost limit オプション」および「SET QUERY_GOVERNOR_COST_LIMIT (Transact-SQL)」を参照してください。
プラン キャッシュにあるクエリ プランの再利用を最適化します。データベース エンジンでは、再利用できる場合に備えてクエリ プランがキャッシュされます。クエリ プランは、キャッシュされなければ再利用することができません。キャッシュされていないクエリ プランは、実行ごとにコンパイルを必要とするため、パフォーマンスの低下を招きます。次の Transact-SQL SET ステートメント オプションを使用すると、キャッシュされたクエリ プランを再利用できなくなります。これらの SET オプションを ON にした Transact-SQL バッチのクエリ プランは、SET オプションを OFF にしてコンパイルした同じバッチで共有することはできません。
SET ANSI_NULL_DFLT_OFF
SET ANSI_NULL_DFLT_ON
SET ANSI_NULLS
SET ANSI_PADDING
SET ANSI_WARNINGS
SET ARITHABORT
SET CONCAT_NULL_YIELDS_NULL
SET DATEFIRST
SET DATEFORMAT
SET FORCEPLAN
SET LANGUAGE
SET NO_BROWSETABLE
SET NUMERIC_ROUNDABORT
SET QUOTED_IDENTIFIER
SET TEXTSIZE
また、各種の SET オプション (ANSI_NULLS、ANSI_NULL_DFLT_ON、ANSI_PADDING、ANSI_WARNINGS、CURSOR_CLOSE_ON_COMMIT、IMPLICIT_TRANSACTIONS、QUOTED_IDENTIFIER) の変更に使用される SET ANSI_DEFAULTS オプションも、キャッシュされたクエリ プランの再利用に影響します。SET ANSI_DEFAULTS を使用して変更できるほとんどの SET オプションが、クエリ プランの再利用に影響する SET オプションに含まれています。
上記の一部の SET オプションは、次の方法を使用して変更することができます。
サーバー全体にかかわる変更については、sp_configure ストアド プロシージャを使用します。詳細については、「sp_configure (Transact-SQL)」を参照してください。
ALTER DATABASE ステートメントの SET 句を使用します。詳細については、「ALTER DATABASE (Transact-SQL)」を参照してください。
OLE DB および ODBC の接続設定を変更します。詳細については、「クライアント ネットワーク構成」を参照してください。
注意 |
---|
SET オプションが原因で発生するクエリ プランの再コンパイルを回避するには、SET オプションを接続時に設定し、接続した状態で変更しないようにしてください。一部の SET オプションは、インデックス付きビューまたは計算列のインデックスを使用できるように、特定の値に設定する必要があります。詳細については、「結果に影響を与える SET オプション」を参照してください。 |