sql-server - 进行 UNION 时针对未知进行优化

标签 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) 

这是目前的实际 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)) 

最佳答案

来自在线图书 ( Query Hints ):

Query hints specify that the indicated hints should be used throughout the query. They affect all operators in the statement. If UNION is involved in the main query, only the last query involving a UNION operation can have the OPTION clause.

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

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

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

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

关于sql-server - 进行 UNION 时针对未知进行优化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17366925/

相关文章:

c# - 从数据库中处理 100 万条记录的技术是什么

sql - 如何在 SQL Server 中按周(7 天)分组

sql-server - SQL Server - 使用空关键字的自由文本搜索

sql-server - 如何从生成的sql返回本地临时表

java - 模拟存储过程

c# - Multi-Tenancy - 为每个租户动态创建数据库

sql-server - 如何使用单个查询在 SQL Server 2008 中创建和更新 View

sql - 您可以在 PostgreSQL 存储过程 IF 子句中执行 WHERE 子句吗?

sql-server - 删除特定SQL Server架构中的所有存储过程

jquery - 为什么即使参数正确,存储过程也不返回 Nothing?