2012-10-15 44 views
0

我有一個存儲過程,它使用一個表值函數在9秒內執行。如果我更改表值函數並刪除where子句,則存儲過程將在3秒內執行。如果我添加了where子句,查詢仍然在3秒內執行。執行計劃優化when where子句被刪除,然後加回

我看了一下執行計劃,看來在刪除where子句之後,執行計劃包含並行性,並且我的表中2個的掃描計數下降爲50000,而65000下降到5和3。將where子句添加回去,優化的執行計劃仍然運行,除非我運行DBCC FREEPROCCACHE。

問題 1.爲什麼只有當我第一次刪除where子句時,SQL Server纔開始爲這兩個查詢使用優化的執行計劃?

  1. 有沒有辦法強制SQL Server使用這個執行計劃?

另外,這是一個參數化的all-in-one查詢,它在where子句中使用(Parameter爲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 
) 
+0

通過在參數where子句中使用ISNULL而不是OR,可以獲得更好的性能。 WHERE dimColor.ExteriorColor像ISNULL(@ExteriorColor,'%') –

回答

0

問題1:SQL服務器仍然繼續使用對沒有where子句的語句執行計劃有效。基本上SQL Server認爲where子句不在那裏。

問題2:使用OPTION(USE PLAN N '')的文章:http://technet.microsoft.com/en-us/library/cc917694.aspx

個人推薦:

  1. 更改查詢,以便您至少有一個強制篩選並建立索引。 或
  2. 將其更改爲動態,並動態應用濾鏡。文章:http://msdn.microsoft.com/en-us/library/ms188001.aspx

希望這會有所幫助。