我正在通过CTE更新自加入的结果表。当选择查看更新的预期结果时,它可以在16秒内返回结果。来自CTE的更新
但是,当我使用相同的语法来尝试实际更新基础表时,它非常慢。
对于我的生活,我无法弄清楚为什么如此戏剧性的放缓。我经常通过CTE更新表格,与同等选择相比,它通常更加快速和合理。
我已经在底层表上尝试过和没有PrimaryKey/Clustered索引,它没有区别。
该联接位于计算列上,因此无法建立索引。
如果SELECT和UPDATE之间的时间差异是两倍,那么它就不是问题。这里的问题是从选择到更新的时间增加的巨大程度。对于选择结果为1323行的16秒,更新其中2行需要59秒,更新4需要1分19秒,更新6需要1分39秒(因此看起来每个附加行增加10秒)。
任何人都可以为我阐明这一点,并提出一种方法来加速?
这里的示例代码:
;WITH CTE AS (SELECT
DENSE_RANK() OVER (Order by
col1,
col2,
col3) SetID,
COUNT(*) OVER (partition by
col1,
col2,
col3) DupsInSet,
row_number() OVER (PARTITION BY
col1,
col2,
col3
ORDER BY
col4 desc) RowInSet,
COUNT(col4) OVER (partition by
col1,
col2,
col3) NonNull,
*
FROM mytable)
在16秒后--The下完成,并返回1323行
select b.col4,a.*
from cte a
join cte b on b.SetID=a.SetID
where a.DupsInSet>1
and a.NonNull>0
and b.RowInSet=1
and a.RowInSet>1
and b.col4 is not null
and a.col4 is null
从这个--Updating用于运行这么长时间,我甚至没有让它完成 - 作为一项测试,我将更新限制在前2名。然后这花了59秒来更新2行
UPDATE TOP(2) a
SET a.col4=b.col4
from cte a
join cte b on b.SetID=a.SetID
where a.DupsInSet>1
and a.NonNull>0
and b.RowInSet=1
and a.RowInSet>1
and b.col4 is not null
and a.col4 is null
为UPDATE https://www.brentozar.com/pastetheplan/?id=Ske_In3_Z
更新选择https://www.brentozar.com/pastetheplan/?id=ByItSnhuW
实际执行计划实际执行计划:
以从SqlZim它跑了4分钟的建议没有完成,在这一点上,我停止了。
然而,随着
- 在模式的改变(谢谢SqlZim)从几个VARCHAR(MAX)列到VARCHAR(?)在哪里?是MAX(LEN(列))
和
- 一些修改SqlZims建议的查询,则更新能够在23秒运行!...其大约是3,300倍:)
这里是最后一个查询(除非有人可以使其工作,而不必列出所有darn列,例如加入对SETID):
(注意,热膨胀系数仍用于从600K +行下过滤原始表)
;WITH CTE AS (SELECT
COUNT(*) OVER (partition by
[col1]
,[col2]
,[col3]
,[col4]
,[col5]
,[col6]
,[col7]
,[col8]
,[col9]
,[col10]
,[col11]
,[col12]
,[col13]
,[col14]
,[col15]
,[col16]
,[col17]
,[col18]
,[col19]
,[col20]
,[col21]
,[col22]
,[col23]) DupsInSet,
COUNT(col24) OVER (partition by
[col1]
,[col2]
,[col3]
,[col4]
,[col5]
,[col6]
,[col7]
,[col8]
,[col9]
,[col10]
,[col11]
,[col12]
,[col13]
,[col14]
,[col15]
,[col16]
,[col17]
,[col18]
,[col19]
,[col20]
,[col21]
,[col22]
,[col23]) NonNull,
*
FROM mytable
)
update a
set a.col24 = b.col24
from cte a
cross apply (
select top 1 i.col24
from cte i
where (i.col1=a.col1 OR (i.col1 is null AND a.col1 is null))
and (i.col2=a.col2 OR (i.col2 is null AND a.col2 is null))
and (i.col3=a.col3 OR (i.col3 is null AND a.col3 is null))
and (i.col4=a.col4 OR (i.col4 is null AND a.col4 is null))
and (i.col5=a.col5 OR (i.col5 is null AND a.col5 is null))
and (i.col6=a.col6 OR (i.col6 is null AND a.col6 is null))
and (i.col7=a.col7 OR (i.col7 is null AND a.col7 is null))
and (i.col8=a.col8 OR (i.col8 is null AND a.col8 is null))
and (i.col9=a.col9 OR (i.col9 is null AND a.col9 is null))
and (i.col10=a.col10 OR (i.col10 is null AND a.col10 is null))
and (i.col11=a.col11 OR (i.col11 is null AND a.col11 is null))
and (i.col12=a.col12 OR (i.col12 is null AND a.col12 is null))
and (i.col13=a.col13 OR (i.col13 is null AND a.col13 is null))
and (i.col14=a.col14 OR (i.col14 is null AND a.col14 is null))
and (i.col15=a.col15 OR (i.col15 is null AND a.col15 is null))
and (i.col16=a.col16 OR (i.col16 is null AND a.col16 is null))
and (i.col17=a.col17 OR (i.col17 is null AND a.col17 is null))
and (i.col18=a.col18 OR (i.col18 is null AND a.col18 is null))
and (i.col19=a.col19 OR (i.col19 is null AND a.col19 is null))
and (i.col20=a.col20 OR (i.col20 is null AND a.col20 is null))
and (i.col21=a.col21 OR (i.col21 is null AND a.col21 is null))
and (i.col22=a.col22 OR (i.col22 is null AND a.col22 is null))
and (i.col23=a.col23 OR (i.col23 is null AND a.col23 is null))
and i.col24 is not null
order by col24 desc
) b
where a.col24 is null
and a.DupsInSet>1
and a.NonNull>0
使用[粘贴该计划@ brentozar.com分享您的执行计划](https://www.brentozar.com/pastetheplan/)这里是说明:[如何使用粘贴计划](https://www.brentozar.com/pastetheplan/instructions/)。样本数据和期望的结果也会有所帮助。 – SqlZim
@SqlZim - 已发布编辑以添加执行计划的链接。链接到选择的示例行https://ibb.co/huyQhQ – tentrade
为什么要从CTE更新CTE?这是什么意思,因为它仅在CTE创建后的第一个声明中可用? – HLGEM