MERGE是否使用tempdb?


12

考虑以下查询:

MERGE [Parameter] with (rowlock) AS target
    USING (SELECT @AreaId, @ParameterTypeId, @Value)
            AS source (AreaId, ParameterTypeId, Value)
    ON (target.AreaId = source.AreaId AND 
        target.ParameterTypeId = source.ParameterTypeId)
    WHEN MATCHED THEN 
        UPDATE SET target.Value = source.Value, @UpdatedId = target.Id
    WHEN NOT MATCHED THEN
        INSERT ([AreaId], [ParameterTypeId], [Value])
        VALUES (source.AreaId, source.ParameterTypeId, source.Value);

统计信息I / O提供以下输出:

表“ ParameterType”。扫描计数0,逻辑读取2,物理读取0,预读读取0,lob逻辑读取0,lob物理读取0,lob预读读取0。
表'Area'。扫描计数0,逻辑读2,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
表'Parameter'。扫描计数1,逻辑读4,物理读0,预读0,lob逻辑读0,lob物理读0,lob预读0。
表'Worktable'。扫描计数1,逻辑读为0,物理读为0,预读为0,lob逻辑读为0,lob物理读为0,lob预读为0。

工作表出现在消息选项卡中,这使我认为tempdb正在被MERGE

我没有在执行计划中看到任何表明需要tempdb的信息

是否MERGE总是使用tempdb?

BOL中有什么可以解释此行为?

在这种情况下会使用INSERTUPDATE更快吗?

剩下

在此处输入图片说明

在此处输入图片说明

这是表格结构

在此处输入图片说明


计划中的线轴是中的工作表tempdb。虽然只有一行,这似乎很奇怪。我想可能有万圣节保护。
马丁·史密斯

我现在看到了。将输入中的数据存储到临时表中以优化倒带。
Craig Efrein

Answers:


8

(扩大我对这个问题的评论。)

如果没有对组合唯一约束AreaIdParameterTypeId,给定的代码被打破,因为@UpdatedId = target.Id将只记录单个行Id

除非您这样说,否则SQL Server无法隐式知道数据的可能状态。应该强制执行约束,或者如果多行有效,则需要更改代码以使用不同的机制来输出Id值。

由于扫描运算符可能会遇到多个匹配行,因此查询必须急于将所有匹配项假脱机以保护万圣节。如注释中所述,约束有效的,因此添加约束不仅将计划从扫描更改为查找,而且还消除了对表假脱机的需要,因为SQL Server知道将为0或0。查找操作符返回1行。


6

如果更新可以更改该行在更新扫描的索引中的位置,则SQL Server需要保护万圣节问题。为此,SQL Server通常在索引扫描后立即在执行计划中插入一个渴望的表假脱机。该运算符基本上会创建相关行的副本,并为此使用tempdb。

在大多数需要万圣节保护的情况下,MERGE语句的更新部分必须遵循相同的规则,并且还使用表假脱机。

虽然我无法确定查询中是否是这种情况,但是由于我不知道索引定义,所以很可能是这里发生的情况。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.