SQL Server 执行计划审查请求

Posted

技术标签:

【中文标题】SQL Server 执行计划审查请求【英文标题】:SQL Server Execution Plan Review Request 【发布时间】:2017-02-02 11:02:59 【问题描述】:

无法理解为什么我的查询需要这么长时间,请寻求优化建议。

update Laserbeak_Main.dbo.ACCOUNT_MPN set
    DateUpgrade = ord.ConnectedDate
                    FROM [ORDER] ord
                    WHERE ord.AccountNumber = Laserbeak_Main.dbo.ACCOUNT_MPN.AccountNumber
                    AND ord.ordertypeID = '2'
                    AND ord.ConnectedDate IS NOT NULL
                    AND DateUpgrade <> ord.ConnectedDate

Execution plan as requested on brentozar.com

更新:根据建议,新查询看起来像这样并且似乎工作得更快。但是,如果您运行查询,它会按预期设置行,然后再次运行它会更新完全相同的行数。转换为选择确认每次都在更新相同的行。 子句应该阻止它,但它没有。我认为这与排序规则有关,但无法确认是否可能在同一数据库中的表级别有不同的排序规则。

;WITH cteOrderInfo AS (
SELECT DISTINCT ord.AccountNumber, ord.ConnectedDate
FROM [ORDER] ord
WHERE ord.ordertypeID = '2'
AND ord.ConnectedDate IS NOT NULL
)
UPDATE Laserbeak_Main.dbo.ACCOUNT_MPN
SET Laserbeak_Main.dbo.ACCOUNT_MPN.DateUpgrade = cteOrderInfo.ConnectedDate
FROM cteOrderInfo
INNER JOIN Laserbeak_Main.dbo.ACCOUNT_MPN acc
ON cteOrderInfo.AccountNumber = acc.AccountNumber
WHERE cteOrderInfo.ConnectedDate <> acc.DateUpgrade

要确认的 SELECT:

;WITH cteOrderInfo AS (
SELECT DISTINCT ord.AccountNumber, ord.ConnectedDate
FROM [ORDER] ord
WHERE ord.ordertypeID = '2'
AND ord.ConnectedDate IS NOT NULL
)
SELECT cteOrderInfo.ConnectedDate, acc.DateUpgrade
FROM cteOrderInfo
INNER JOIN Laserbeak_Main.dbo.ACCOUNT_MPN acc
ON cteOrderInfo.AccountNumber = acc.AccountNumber
WHERE cteOrderInfo.ConnectedDate <> acc.DateUpgrade

选择结果示例:

【问题讨论】:

与查询性能无关,但如果您稍微重新构造查询,可能会更易于阅读:UPDATE acc SET DateUpgrade = ord.ConnectedDate FROM dbo.ACCOUNT_MPN acc INNER JOIN dbo.ORDER ord ON acc.AccountNumber = dbo.AccountNumber AND ord.orderTypeID = 2 ORDER 表中的 AccountNumber 列不是唯一的,是吗?如果是这样,除非您的WHERE 子句充分限制了数据集,否则查询将多次更新ACCOUNT_MPN 表中的每一行。为避免这种情况,您可以:a) 代替FROM ORDER。使用带有DISTINCT 关键字的子查询;乙)。使用带有GROUP BY 子句的子查询;或 c)。向现有的WHERE 子句添加附加条件。 你能把执行计划贴在这里并分享链接:brentozar.com/pastetheplan 已更新计划 为什么要投反对票? 【参考方案1】:

正如 Serge 所建议的,我们没有唯一的行。

我们得出的解决方案:

;WITH cteSourceStuff AS (
      SELECT AccountNumber, MpnUpgrade, MAX(DateConnected) maxConnDate
      FROM ORDER_DETAIL, [ORDER]
      WHERE ORDER_DETAIL.OrderID = [ORDER].OrderID
      AND LEN(MpnUpgrade) > 10
      AND OrderTypeID = 2
      GROUP BY AccountNumber, MpnUpgrade
      )
      UPDATE Laserbeak_Main.dbo.ACCOUNT_MPN set
              DateUpgrade = cteSourceStuff.maxConnDate
              FROM cteSourceStuff
              WHERE cteSourceStuff.MpnUpgrade = ACCOUNT_MPN.Mpn
              AND cteSourceStuff.AccountNumber = ACCOUNT_MPN.AccountNumber
              AND DateUpgrade <> cteSourceStuff.maxConnDate

之所以有效,是因为最初删除了重复项,然后我们只更新我们实际定位的行。我们之前遇到问题的原因是 SQL 正在更新它找到的第一行,然后当我们重新运行或运行 select 时,它会返回与键匹配但之前没有更新的行。

【讨论】:

以上是关于SQL Server 执行计划审查请求的主要内容,如果未能解决你的问题,请参考以下文章

SQL SERVER如何应用执行计划

sql server 执行计划(execution plan)介绍

sql server 如何执行一项计划任务

SQL Server如何固定执行计划

引用:初探Sql Server 执行计划及Sql查询优化

SQL SERVER执行计划和索引优化基础