执行计划优化何时删除where子句然后添加回来

时间:2012-10-15 21:34:00

标签: sql-server-2008 sql-optimization sql-execution-plan

我有一个使用表值函数的存储过程,该函数在9秒内执行。如果我更改了表值函数并删除了where子句,则存储过程将在3秒内执行。如果我添加where子句,查询仍然会在3秒内执行。

我看了一下执行计划,看来我删除了where子句后,执行计划包括并行性,我的2个表的扫描计数下降为50000和65000下降到5和3.我添加后在where子句中,优化的执行计划仍然运行,除非我运行DBCC FREEPROCCACHE。

问题 1.为什么只有在我第一次删除where子句时,SQL Server才开始对两个查询使用优化的执行计划?

  1. 有没有办法强制SQL Server使用此执行计划?
  2. 此外,这是一个参数化的一体化查询,它在where子句中使用(参数为null或参数),我认为这对性能不利。

    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
    )
    

1 个答案:

答案 0 :(得分: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
  3. 希望这有帮助。