MS SQL Server 2000/2005ストアドプロシージャのパフォーマンス

ストアドプロシージャがクエリのパフォーマンスを低下させる可能性がある状況を検討します。





MS SQL Server 2000でストアドプロシージャをコンパイルする場合、ストアドプロシージャはプロシージャキャッシュに配置されます。これは、ストアドプロシージャコードの解析、最適化、およびコンパイルの必要性を排除することにより、実行時のパフォーマンスを向上させるのに役立ちます。

一方、逆の効果をもたらす可能性がある落とし穴は、ストアドプロシージャのコンパイルされたコードのストレージに隠されています。

事実、ストアドプロシージャをコンパイルすると、プロシージャコードを構成する演算子の実行計画がそれぞれコンパイルされ、コンパイルされたストアドプロシージャがキャッシュされると、その実行計画もキャッシュされるため、ストアドプロシージャは特定の状況とクエリパラメーターに対して最適化されません。

これを実証するために小さな実験を実施します。



ステップ1 。 データベースの作成。

実験のために、別のデータベースを作成します。



CREATE DATABASE test_sp_perf

オン(NAME = 'test_data'、FILENAME = 'c:\ temp \ test_data'、SIZE = 1、MAXSIZE = 10、FILEGROWTH = 1Mb)

ログオン(NAME = 'test_log'、FILENAME = 'c:\ temp \ test_log'、SIZE = 1、MAXSIZE = 10、FILEGROWTH = 1Mb)



ステップ2.テーブルを作成します。

CREATE TABLE sp_perf_test(column1 int、column2 char(5000))



ステップ3.テーブルにテスト行を入力します。 重複行は意図的にテーブルに追加されます。 1〜10,000の番号を持つ10,000行、および50,000の番号を持つ10,000行。



DECLARE @i int

SET @ i = 1

一方で(@i <10000)

開始

INSERT INTO sp_perf_test(column1、column2)VALUES(@ i、 'Test string#' + CAST(@i as char(8)))

INSERT INTO sp_perf_test(column1、column2)VALUES(50000、 'Test string#' + CAST(@i as char(8)))

SET @ i = @ i + 1

終了



SELECT COUNT(*)FROM sp_perf_test

行く



ステップ4.非クラスター化インデックスの作成。 実行計画はプロシージャとともにキャッシュされるため、インデックスはすべての呼び出しで同じように使用されます。



sp_perf_testのCL_perf_test ONの非クラスター化インデックスの作成(column1)

行く



ステップ5.ストアドプロシージャの作成。 プロシージャは、条件を使用してSELECTステートメントを実行するだけです。



CREATE PROC proc1(@param int)

として

SELECT column1、column2 FROM sp_perf_test WHERE column1 = @ param

行く



ステップ6.ストアドプロシージャを開始します。 脆弱な手順を開始する場合、選択的なパラメーターが特別に使用されます。 手順の結果、1行が取得されます。 実行計画は、非クラスター化インデックスの使用を次のように示します。 クエリは選択的であり、これが文字列を抽出する最良の方法です。 単一の行をフェッチするために最適化されたプロシージャは、プロシージャキャッシュに格納されます。



EXEC proc1 1234

行く







ステップ7.非選択パラメーターを使用してストアード・プロシージャーを開始します。 パラメーターとして50,000の値が使用されます。このような最初の列の値がそれぞれ約10,000の行は、非クラスター化インデックスを使用し、ブックマークルックアップ操作は非効率的ですが、実行プランを含むコンパイル済みコードは手続き型キャッシュに格納されるため、使用されます。 実行計画には、これと、ブックマークの検索操作が9999行に対して実行されたという事実が示されています。



EXEC proc1 50,000

行く







ステップ8.最初のフィールドが50,000に等しい行をフェッチする別のクエリを実行する場合、クエリは最適化され、最初の列の特定の値でコンパイルされます。 その結果、クエリオプティマイザーはフィールドが何度も複製されていると判断し、テーブルスキャン操作の使用を決定します。この場合、非クラスター化インデックスを使用するよりもはるかに効率的です。



SELECT column1、column2 FROM sp_perf_test WHERE column1 = 50000

行く







したがって、ストアドプロシージャを使用してもクエリのパフォーマンスが常に向上するとは限りません。 可変数の行で結果を処理し、異なる実行プランを使用するストアドプロシージャについては、十分に注意する必要があります。

スクリプトを使用して、MS SQLサーバーで実験を繰り返すことができます。






All Articles