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 or 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 server 仍然继续使用没有where 子句的执行计划valid for statement。基本上 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

希望这可以帮助。

于 2012-10-16T13:35:41.460 回答