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 执行计划审查请求的主要内容,如果未能解决你的问题,请参考以下文章