ひどく実行するストアドプロシージャがあります。変数を宣言するときは、その値を設定してから、ステートメントの実行に1時間以上かかるwhere句で使用します。where句の変数をハードコーディングすると、1秒未満で実行されます。
私は実行計画を通してそれの何が悪いのかを調べ始めました。UNIONと共通テーブル式を使用するビューから値を選択するため、いくつかの宣言された変数を渡そうとすると、実行プランはいくつかのハッシュ一致を作成するように見えます。
/*************ストアドプロシージャの開始***************/ 手順の作成GetFruit @ColorId bigint、 @SeasionId bigint 再コンパイルあり なので 始める 選択する 名前 から [Apple_View] A/*これは下のビューです*/ インナージョイント[フルーツ]F オン(F.ColorId = @ColorId AND A.FruitId = F.FruitId) どこ (A.ColorId = @ColorId と A.SeasonId = @SeasonId) 終わり /*************ストアドプロシージャの終了***************/ /*************ビューの開始***************/ 果物付き(FruitId、ColorId、SeasonId)AS (( -アンカーメンバー 選択する F.FruitId 、F.ColorId 、F.SeasonId から ((( 距離を選択 EF.FruitId 、EF.ColorId 、EF.SeasonId 、EF.ParentFruitId から エキゾチックフルーツEF インナージョインフルーツFR ON FR.FruitId = EF.FruitId 連合 距離を選択 SF.FruitId 、SF.ColorId 、SF.SeasonId 、SF.ParentFruitId から StinkyFruit SF インナージョインフルーツFR ON FR.FruitId = SF.FruitId 連合 距離を選択 CF.FruitId 、CF.ColorId 、CF.SeasonId 、CF.ParentFruitId から CrazyFruit CF インナージョインフルーツFR ON FR.FruitId = CF.FruitId ))f ユニオンオール -再帰的な親の果実 選択する FS.FruitId 、FS.ColorId 、FS.SeasonId 、FS.ParentFruitId から フルーツFS 内部結合MasterFruitMF ONMF。[ParentFruitId]=fs。[FruitId] )。 距離を選択 FS.FruitId 、FS.ColorId 、FS.SeasonId から フルーツFS /*************ビューの終わり***************/ /*実行するには*/ EXEC GetFruit 1,3
設定値を使用してストアドプロシージャを実行すると、1時間以上かかります。これが、実行プランです。
DECLARE値とSET値を削除してストアドプロシージャを実行し、Where句を次のステートメントに設定すると、1秒未満で実行され、実行プランは次のようになります。
WHERE(A.ColorId = 1 AND A.SeasonId = 3)
最初の変数がハッシュセットを使用しているのに対し、ハードコードされた変数がどのようにインデックスを使用しているかに注目してください。何故ですか?where句のハードコードされた値が宣言された変数と異なるのはなぜですか?
-------これは@user1166147の助けを借りて最終的に実行されたものです------
sp_executesqlを使用するようにストアドプロシージャを変更しました。
手順の作成GetFruit @ColorId bigint、 @SeasionId bigint 再コンパイルあり なので 始める DECLARE @SelectString nvarchar(max) SET @SelectString = N'SELECT 名前 から [Apple_View] A/*これは下のビューです*/ インナージョイント[フルーツ]F オン(F.ColorId = @ColorId AND A.FruitId = F.FruitId) どこ (A.ColorId ='+ CONVERT(NVARCHAR(MAX)、@ColorId)+' と A.SeasonId ='+ CONVERT(NVARCHAR(MAX)、@SeasonId)+') ' EXEC sp_executesql @SelectString 終わり