以下の2つのクエリのそれぞれが、SQL Serverで実行プランを生成する方法を誰かに説明してもらいたいと思います。私の関数_[dbo].[GetAdditionalProjectDatesForCalendar]
_はITVF(インラインテーブル値関数)です。
動的SQL
_sp_executesql N'SELECT * FROM [dbo].[GetAdditionalProjectDatesForCalendar]
(@Parameter1,@Parameter2)', @Parameter1 = 'Value1', @Parameter2 = 'Value2'
_
インラインSQL
_SELECT * FROM [dbo].[GetAdditionalProjectDatesForCalendar]
('Value1','Value2')
_
動的SQLは、私が取り組んでいるC#アプリケーションから生成されたものであり、ほとんどの場合、インラインSQLと同じように機能しますが、_@Parameter1
_および_@Parameter2
_の特定の値ではパフォーマンスが低下します。
これが パラメータスニッフィング によってどのように発生するかを読み、動的SQLでoption(recompile)
を使用しようとしましたが、パフォーマンスが完全に向上するわけではありません。
option(recompile)
を使用してオンザフライで作成するのではなく、指定されたパラメーターの正確な実行プランを使用するように、C#にインラインSQLを作成させる方法を見つける必要があると感じています。また、パラメーター化を使用せずに動的SQLを作成することでこれを実行できると思いますが、SQLインジェクションのリスクが生じることはわかっています。
OPTION (RECOMPILE)
を使用した_sp_executesql
_プランは、パラメーターの埋め込みも有効にして、各呼び出しの特定のパラメーター値に対して完全に最適化する必要があります。
質問で参照されている記事に対するItzikBen-Ganのコメントから AdventureWorks の例を取り上げます。
_CREATE FUNCTION dbo.F
(
@NameLike nvarchar(50),
@Sort tinyint
) RETURNS TABLE
AS
RETURN
SELECT TOP (5)
ProductID,
Name
FROM Production.Product
WHERE
@NameLike IS NULL
OR Name LIKE @NameLike
ORDER BY
CASE WHEN @Sort = 1 THEN ProductID ELSE NULL END ASC,
CASE WHEN @Sort = 2 THEN ProductID ELSE NULL END DESC,
CASE WHEN @Sort = 3 THEN Name ELSE NULL END ASC,
CASE WHEN @Sort = 4 THEN Name ELSE NULL END DESC;
_
実行計画:
_SELECT *
FROM dbo.F(N'K%', 3);
_
...インライン化されている特定のパラメーター値を示します(したがって、_@NameLike IS NULL
_が最適化され、シークが有効になります)が、パラメーターの埋め込みは行われないため、_ORDER BY
_句のトップNソートがあります。
再コンパイルクエリヒントを追加すると、パラメータの埋め込みが有効になっている(並べ替えなし)特定の値のプランが生成されます。
_SELECT *
FROM dbo.F(N'K%', 3)
OPTION (RECOMPILE);
_
クエリを_sp_executesql
_でラップすると、値が明示的にパラメータ化されているため、インライン化も埋め込みも行われません。
_EXECUTE sys.sp_executesql
N'SELECT * FROM dbo.F(@NameLike, @Sort)',
N'@NameLike nvarchar(50), @Sort tinyint',
@NameLike = N'K%', @Sort = 3;
_
OPTION (RECOMPILE)
を追加すると、両方の最適化が再び有効になります。
_EXECUTE sys.sp_executesql
N'SELECT * FROM dbo.F(@NameLike, @Sort) OPTION (RECOMPILE)',
N'@NameLike nvarchar(50), @Sort tinyint',
@NameLike = N'K%', @Sort = 3;
_