0

9 秒で実行されるテーブル値関数を使用するストアド プロシージャがあります。テーブル値関数を変更して where 句を削除すると、ストアド プロシージャは 3 秒で実行されます。where 句を追加し直しても、クエリは 3 秒で実行されます。

実行計画を調べたところ、where 句を削除した後、実行計画に並列処理が含まれ、2 つのテーブルのスキャン数が 50000 と 65000 から 5 と 3 に減少したようです。where 句を追加した後DBCC FREEPROCCACHE を実行しない限り、最適化された実行プランは引き続き実行されます。

質問 1. 最初に where 句を削除した場合にのみ、SQL Server が両方のクエリに対して最適化された実行プランを使用し始めるのはなぜですか?

  1. SQL Server にこの実行計画を強制的に使用させる方法はありますか?

また、これは where 句で (Parameter is null または Parameter) を使用するパラメーター化されたオールインワン クエリであり、パフォーマンスに悪いと思います。

RETURNS TABLE 
AS
RETURN 
(
SELECT  TOP (@PageNumber * @PageSize)
                CASE
                    WHEN @SortOrder = 'Expensive' THEN ROW_NUMBER()     OVER (ORDER BY SellingPrice DESC)
                WHEN @SortOrder = 'Inexpensive' THEN ROW_NUMBER() OVER (ORDER BY SellingPrice ASC)                  
                WHEN @SortOrder = 'LowMiles' THEN ROW_NUMBER() OVER (ORDER BY Mileage ASC)
                WHEN @SortOrder = 'HighMiles' THEN ROW_NUMBER() OVER (ORDER BY Mileage DESC)
                WHEN @SortOrder = 'Closest' THEN ROW_NUMBER() OVER (ORDER BY P1.Distance ASC)       
                WHEN @SortOrder = 'Newest' THEN ROW_NUMBER() OVER (ORDER BY [Year] DESC)    
                WHEN @SortOrder = 'Oldest' THEN ROW_NUMBER() OVER (ORDER BY [Year] ASC)                     
                ELSE ROW_NUMBER() OVER (ORDER BY InventoryID ASC)
            END as rn,
            P1.InventoryID,
            P1.SellingPrice,
            P1.Distance,
            P1.Mileage,
            Count(*) OVER () RESULT_COUNT,
            dimCarStatus.[year]
    FROM    (SELECT InventoryID, SellingPrice, Zip.Distance, Mileage, ColorKey, CarStatusKey, CarKey FROM facInventory
                JOIN @ZipCodes Zip
                ON   Zip.DealerKey = facInventory.DealerKey) as P1
    JOIN    dimColor
            ON dimColor.ColorKey = P1.ColorKey
    JOIN    dimCarStatus
            ON dimCarStatus.CarStatusKey = P1.CarStatusKey  
    JOIN    dimCar
            ON dimCar.CarKey = P1.CarKey                        
    WHERE
            (@ExteriorColor is NULL OR dimColor.ExteriorColor like @ExteriorColor) AND
            (@InteriorColor is NULL OR dimColor.InteriorColor like @InteriorColor) AND
            (@Condition is NULL OR dimCarStatus.Condition like @Condition) AND
            (@Year is NULL OR dimCarStatus.[Year] like @Year) AND
            (@Certified is NULL OR dimCarStatus.Certified like @Certified) AND
            (@Make is NULL OR dimCar.Make like @Make) AND
            (@ModelCategory is NULL OR dimCar.ModelCategory like @ModelCategory) AND    
            (@Model is NULL OR dimCar.Model like @Model) AND
            (@Trim is NULL OR dimCar.Trim like @Trim) AND
            (@BodyType is NULL OR dimCar.BodyType like @BodyType) AND
            (@VehicleTypeCode is NULL OR dimCar.VehicleTypeCode like @VehicleTypeCode) AND
            (@MinPrice is NULL OR P1.SellingPrice >= @MinPrice) AND
            (@MaxPrice is NULL OR P1.SellingPrice < @MaxPrice) AND
            (@Mileage is NULL OR P1.Mileage < @Mileage)
    ORDER   BY
            CASE
                WHEN @SortOrder = 'Expensive' THEN -SellingPrice
                WHEN @SortOrder = 'Inexpensive' THEN SellingPrice 
                WHEN @SortOrder = 'LowMiles' THEN Mileage
                WHEN @SortOrder = 'HighMiles' THEN -Mileage
                WHEN @SortOrder = 'Closest' THEN P1.Distance        
                WHEN @SortOrder = 'Newest' THEN -[YEAR]
                WHEN @SortOrder = 'Oldest' THEN [YEAR]                  
                ELSE InventoryID 
            END
)
4

1 に答える 1

0

質問 1: SQL サーバーは、where 句のないステートメントに対して有効な実行プランを引き続き使用します。基本的に SQL Server は where 句が存在しないと考えています。

質問 2: OPTION (USE PLAN N'') を使用する記事: http://technet.microsoft.com/en-us/library/cc917694.aspx

個人的なおすすめ:

  1. クエリを変更して、少なくとも 1 つの必須フィルターとインデックスを作成します。また
  2. 動的に変更し、フィルターを動的に適用します。記事: http://msdn.microsoft.com/en-us/library/ms188001.aspx

お役に立てれば。

于 2012-10-16T13:35:41.460 に答える