3

私の意見では、非常に奇妙な問題があります。次の方法でUDFを呼び出すと:

DECLARE @contact_id uniqueidentifier
DECLARE @group_id uniqueidentifier
SET @group_id = 'EE57E2AD-204B-4078-AFA4-11FA8375C2FD'
set @contact_id = 'E6EFCC9F-9D1C-4C38-A950-C45372F2A6D2'

SELECT COUNT( ID )  AS [CountAll] 
FROM [Document] As [Document] 
WHERE ([Document].[ID] IN (SELECT ID FROM [fs_Document_View_ee57e2ad_204b_4078_afa4_11fa8375c2fd](@contact_id, @group_id)))

4 秒間実行され、次の実行計画が得られます

次のようにハードコードされたパラメーターを使用してUDFを呼び出すと、次のようになります。

SELECT COUNT( ID )  AS [CountAll] 
FROM [Document] As [Document] 
WHERE ([Document].[ID] IN (SELECT ID FROM [fs_Document_View_ee57e2ad_204b_4078_afa4_11fa8375c2fd]('E6EFCC9F-9D1C-4C38-A950-C45372F2A6D2', 'EE57E2AD-204B-4078-AFA4-11FA8375C2FD')))

この実行計画を取得します。遅く、91 秒かかります。

なぜこれが起こっているのか誰にも説明できますか?

この関数は、同じパラメーターを渡して他の 4 つのネストされた関数を呼び出します。アイテムの表示権限に関連しています。

事前に助けてくれてありがとう。

アップデート

Ivan G. が言及したこの記事のオプション 2 を使用しました。

問題はパラメータ スニッフィングであり、オプション 2 で問題が解決されました。

パラメータ スニッフィングの問題を解決する別の方法は、パラメータ スニッフィングを無効にすることです。これは、スイッチまたはデータベース オプションでは実行できませんが、ストアド プロシージャ コードのスクリプト内から実行できます。>ストアド プロシージャを作成して、パラメーター スニッフィングを無効にする方法の例を次に示します。

DROP PROC [dbo].[DisplayBillingInfo]
GO
CREATE PROC [dbo].[DisplayBillingInfo]
  @BeginDate DATETIME,
  @EndDate DATETIME
WITH RECOMPILE
AS
DECLARE @StartDate DATETIME;
DECLARE @StopDate DATETIME;
SET @StartDate = @BeginDate;
SET @StopDate = @EndDate;
SELECT BillingDate, BillingAmt
  FROM BillingInfo
  WHERE BillingDate between @StartDate AND @StopDate; 

パラメータ スニッフィングを無効にするために行ったのは、ストアド プロシージャ内でのパラメータ値の使用方法を変更することだけでした。プロシージャ内に 2 つの異なるローカル変数 (@StartDate と @EndDate) を作成し、これらの変数を渡されたパラメーターに設定してから、BETWEEN 条件でローカル変数を使用することで、パラメーター スニッフィングを無効にすることができました。オプティマイザーは実際の SELECT ステートメントでパラメーターの値を識別できないため、パラメーター スニッフィングは無効になっています。SQL Server は、ストアド プロシージャの呼び出しに使用されたパラメーター値を特定できないため、オプティマイザーは統計に基づいて一般的なプランを作成します。

上記のコードを使用してストアド プロシージャを実行すると、狭い範囲の日付または 1 年分の日付を使用して、コンパイルされた実行プランは常に "インデックス スキャン" 操作を実行します。パラメータ sniff がオフになっていることがわかります。これは、日付の範囲が短いと、通常はインデックス シーク操作が作成されることがわかっているためです。

4

1 に答える 1

2

パラメータ化によるものだと思います。クエリの最初のバージョンはパラメーター化されていますが、2 番目のバージョンはパラメーター化されていません。「パラメータ化されたクエリは再コンパイルが少なくて済み、動的に構築されたクエリは非常に頻繁にコンパイルと再コンパイルが必要です」( source )

パラメーターを使用して作成されたバージョンのクエリの場合、実行計画が作成され、再利用されます。" SQL クエリにパラメーターがある場合、SQL Server は、「パラメーター スニッフィング」と呼ばれるプロセスを介して、パフォーマンスを向上させるために、それらに合わせた実行計画を作成します。この計画は保存されます。通常は最適な実行計画であるため、再利用されます」(source)。

于 2013-02-12T08:15:44.220 に答える