2

実行計画を構築するために SQL クエリでバインド パラメータを使用する方法を教えてください。

多くのシナリオでは、開発者は動的 SQL クエリを作成し、クエリに適切な値を配置します。

これを読んでいる間、http://use-the-index-luke.com/sql/where-clause/bind-parameters同じ実行計画を使用するため、バインドパラメーターを使用するとパフォーマンスが向上すると思います。

SP で構築された動的クエリでバインド パラメータを使用した例を次に示します。

CREATE Procedure GetEmployee 
AS
(
@eName NVARCHAR(100),
@eDept NVARCHAR(50)
)

BEGIN
Declare @sql NVarchar(MAX)
DECLARE @params NVARCHAR(MAX)

 SELECT @params = N'@name nvarchar(100), ' +  
                    N'@dept nvarchar(50) ' 

SET @sql='Select EmpId, Name from Employee where Name=@name AND Department=@dept'

sp_executesql @sql, @params, @eName, @eDept

END

WHERE Name='''+@eName+''' と比較して、これが実際にどのようにパフォーマンスを向上させるのでしょうか?

4

3 に答える 3

2

この記事で示唆されているように、SQL Server クエリ オプティマイザーはsp_execute_sql のキャッシュされた実行プランを使用できます。ドキュメントは非常に明確です。そして、ただの利点executeは、クエリがプラン内の何かと一致する可能性が高いことです。

プラン自体についてのメモ。クエリ プランは、パラメーターを指定してクエリを初めて実行したときに生成されます。これは、キャッシュに配置されるものです。あなたのような単純なクエリの場合、クエリ プランは後続の呼び出しに適しているはずです。ただし、この場合でも、テーブル内の 10 行とインデックスから開始し、クエリ プランがテーブルをスキャンすることを決定する状況が発生する可能性があります。さらに 100,000 行を追加すると、それがキャッシュされた計画であるため、(サーバーを再起動するか、他の方法でキャッシュを空にするまで) スキャンを実行する必要があります。

ただし、パラメーターの値がクエリ プランに影響を与える場合もあります。そのため、毎回クエリを再コンパイルすることは悪い考えではないかもしれません。クエリが一定時間 (秒単位) 実行される場合、コンパイルのオーバーヘッドは小さい可能性があります。

于 2013-02-23T17:57:05.703 に答える
1

バインド変数の利点は、RDBMS が

  1. ステートメントを解析/コンパイルする必要はなく、

  2. 実行計画を何度も評価する必要はありません。

通常、一定数のステートメントと実行計画がキャッシュされるため、ここでいくらかの時間が節約されます。ただし、このキャッシュを何千もの同様のステートメントでいっぱいにすると、それほど役に立ちません。

したがって、最終的にステートメント自体のコア実行は速くなりません - 周りのもの (解析、コンパイル、実行計画の作成) だけです。

于 2013-02-23T17:53:50.993 に答える
1

WHERE Name='''+@eName+''' と比較して、これが実際にどのようにパフォーマンスを向上させるのでしょうか?

他の人が述べたことに基づいて構築するだけです。sp_executesql のプラン キャッシュに入る内容は、そのメソッドを呼び出すすべてのユーザーに適用可能なプランになります。変数のプレースホルダーがあり、実行時に適用されます。新しいプランを作成する必要がないため、コストを節約できます。

さらに、これが大きな違いになる可能性があります。前者では、渡されたすべての変数の組み合わせに対して1 つのプランが生成されるということです。後者では、変数の組み合わせごとに 1 つのクエリ プランを取得します。論理的に同じ Index Seek、Sort などの演算子が適用される可能性がありますが、プラン内のプレースホルダーの代わりに、eName = 'Bob' のプランが 1 つ、eName = 'William' のプランが 1 つなどになります。

これらの独自のプランを持つことの欠点は、他のプランがキャッシュされるために使用可能なメモリが奪われることです。プランがキャッシュにありませんか? コンパイルしておっと、プラン キャッシュがいっぱいです。使用頻度の最も低いプランを選択して、それを除外します。次のクエリが入ってくると、ビニングしたばかりのプランが必要になり、プラン キャッシュのスワッピング サイクルが続きます。

最後に、少なくとも .NET 側に関して注意すべきことがあります。リンクされた例では、このコード行はcmd.Parameters.AddWithValue("@subsidiary_id", subsidiary_id);整数を扱っているため問題ありません。イントはイントはイント。ただし、上記のクエリをインライン化する場合、パラメーター@eName@eDepartmentは異なるクエリ プランになる可能性があります。これは、AddWithValueメソッドが推測を行い、変数の一貫した定義が得られない可能性があるためです。1 つが nvarchar(30) で、次が nvarchar(29) であると判断される場合があり、これで 2 つの計画ができました。ストアド プロシージャを使用すると、パラメータによってサイズが定義され、推測が必要ないため、この懸念が軽減されます。

于 2013-02-23T20:46:35.353 に答える