在做UNION时优化UNKNOWN

Sle*_*lee 5 sql-server stored-procedures

所以我在SP中有一些非常慢的查询我需要加速,我一直在使用OPTIMIZE FOR UNKNOWN并且看到性能急剧上升.我仍然有一个查询真的很慢,我想应用它但它包含一个2个SQL查询的UNION,所以我的问题是我是否应用OPTIMIZE FOR UNKNOWN?

这是我的SP清晰度的简单版本:

SELECT * FROM MyTable ManufacturerID=@ManufacturerID and tStamp > @tStamp
OPTION (OPTIMIZE FOR (@ManufacturerID UNKNOWN, @tStamp UNKNOWN)) 
UNION
SELECT * FROM MyTable ManufacturerID=@ManufacturerID
OPTION (OPTIMIZE FOR (@ManufacturerID UNKNOWN) 
Run Code Online (Sandbox Code Playgroud)

这是现在的实际SP:

SELECT * FROM (
SELECT ROW_NUMBER() OVER(ORDER BY Products.ItemID) AS RowNum, *
    FROM
    (
    SELECT  Products.ProductID, Products.ItemID, Products.ManufacturerID,
          CategoryID = NULL, CategoryName = NULL, 
          CategoryProductID = NULL,  Products.ItemName, Products.Description, Products.Notes, 
                      Products.Dimensions, Products.BasePrice, Products.OrderMinimumQuantity, 
                      ContainerMinimumQuantity = 
                        CASE  COALESCE(Products.ContainerMinQty, 0)
                            WHEN 0 THEN Products.OrderMinimumQuantity
                            ELSE Products.ContainerMinQty
                        END 
                      , Products.OrderMultipleQuantity, Products.OnHandQuantity, 
                      Products.Category, Products.IntroDate, Products.BackOrderDate, Products.UPC, Products.PriceLevel1, Products.PriceLevel2, Products.PriceLevel3, 
                      Products.PriceLevel4, Products.PriceLevel5, Products.PriceLevel6, Products.PriceLevel7, Products.PriceLevel8, Products.PriceLevel9, Products.PieceBox, 
                      Products.Cubes, Products.UnitOfMeasure, Products.UDF1, Products.UDF2, Products.UDF3, Products.UDF4, Products.UDF5, Products.AdditionalImageCount, 
                     PhotoName= LOWER(Products.PhotoName),  Products.Discontinued, Products.ModifiedOn, 
                        Products.IsDeleted, Products.PriceLevel10, Products.PriceLevel11, Products.PriceLevel12, Products.PriceLevel13, 
                      Products.PriceLevel14, Products.PriceLevel15, Products.PriceLevel16, Products.PriceLevel17, Products.PriceLevel18, Products.PriceLevel19, Products.PriceLevel20, 
                      Products.Weight, Products.DimensionsMetric, Products.Source, Products.InventoryStatus, Products.CatalogCode, Products.CatalogName, 
                       SortOrder = NULL,
                       Products.reportCategory,Products.additionalPhotos,Products.udf6,Products.udf7,Products.udf8,
                       Products.udf9,Products.udf10,Products.udf11,Products.udf12,Products.udf13,Products.udf14,Products.udf15,Products.udf16,
                       Products.udf17,Products.udf18,Products.udf19,Products.udf20, Products.showRelatedFor,Products.showChildFor
FROM    
CategoryProducts (nolock) RIGHT OUTER JOIN
                      Products (nolock) ON CategoryProducts.ManufacturerID = Products.ManufacturerID AND CategoryProducts.ItemID = Products.ItemID
WHERE     (Products.ManufacturerID = @ManufacturerID)
            AND 
            (Products.ModifiedOn > @tStamp ) AND  ((CategoryProducts.IsDeleted = 1) OR (CategoryProducts.IsDeleted IS NULL)
            )

            UNION

            SELECT Products.ProductID, Products.ItemID, Products.ManufacturerID, Categories.CategoryID, Categories.CategoryName, CategoryProducts.CategoryProductID,  Products.ItemName, Products.Description, Products.Notes, 
                      Products.Dimensions, Products.BasePrice, Products.OrderMinimumQuantity, 
                      ContainerMinimumQuantity = 
                        CASE  COALESCE(Products.ContainerMinQty, 0)
                            WHEN 0 THEN Products.OrderMinimumQuantity
                            ELSE Products.ContainerMinQty
                        END 
                      , Products.OrderMultipleQuantity, Products.OnHandQuantity, 
                      Products.Category, Products.IntroDate, Products.BackOrderDate, Products.UPC, Products.PriceLevel1, Products.PriceLevel2, Products.PriceLevel3, 
                      Products.PriceLevel4, Products.PriceLevel5, Products.PriceLevel6, Products.PriceLevel7, Products.PriceLevel8, Products.PriceLevel9, Products.PieceBox, 
                      Products.Cubes, Products.UnitOfMeasure, Products.UDF1, Products.UDF2, Products.UDF3, Products.UDF4, Products.UDF5, Products.AdditionalImageCount, 
                     PhotoName= LOWER(Products.PhotoName),  Products.Discontinued, Products.ModifiedOn, 
                        CategoryProducts.IsDeleted, Products.PriceLevel10, Products.PriceLevel11, Products.PriceLevel12, Products.PriceLevel13, 
                      Products.PriceLevel14, Products.PriceLevel15, Products.PriceLevel16, Products.PriceLevel17, Products.PriceLevel18, Products.PriceLevel19, Products.PriceLevel20, 
                      Products.Weight, Products.DimensionsMetric, Products.Source, Products.InventoryStatus, Products.CatalogCode, Products.CatalogName, 
                       CategoryProducts.SortOrder,
                       Products.reportCategory,Products.additionalPhotos,Products.udf6,Products.udf7,Products.udf8,
                       Products.udf9,Products.udf10,Products.udf11,Products.udf12,Products.udf13,Products.udf14,Products.udf15,Products.udf16,
                       Products.udf17,Products.udf18,Products.udf19,Products.udf20, Products.showRelatedFor,Products.showChildFor
FROM      Categories (nolock) INNER JOIN
                      CategoryProducts (nolock) ON Categories.CategoryID = CategoryProducts.CategoryID INNER JOIN
                      Products (nolock) ON CategoryProducts.ManufacturerID = Products.ManufacturerID AND CategoryProducts.ItemID = Products.ItemID
WHERE     (Products.ManufacturerID = @ManufacturerID)
            AND 
            (Products.ModifiedOn > @tStamp OR  CategoryProducts.ModifiedOn > @tStamp)
            )  AS Products
        ) AS C  WHERE RowNum >= @StartRow AND RowNum <= @EndRow ORDER BY ItemID, ManufacturerID
    OPTION (OPTIMIZE FOR (@ManufacturerID UNKNOWN, @StartRow UNKNOWN, @EndRow UNKNOWN, @tStamp UNKNOWN)) 
Run Code Online (Sandbox Code Playgroud)

Ian*_*ton 3

来自在线书籍(查询提示):

查询提示指定应在整个查询中使用指示的提示。它们影响语句中的所有运算符。如果主查询中涉及 UNION,则只有涉及 UNION 操作的最后一个查询才能包含 OPTION 子句。

因此,这是非常明确的,您只能使用OPTION一次,而不是像您的示例中那样使用两次。

这是有道理的,因为即使有两条SELECT语句放在一起,SQL Server 仍会将其视为一个整体语句,以便进行编译和优化。

这确实意味着,如果您想在构成的不同语句中使用不同的提示,则UNION必须采用不同的方式,例如使用 TEMP 表来存储临时结果。

因此,在您的具体示例中,即使仅@tStamp在第一个语句中,您仍然可以根据需要SELECT在 one 子句中引用它。OPTION