MERGE 是否使用 tempdb?

Cra*_*ein 12 sql-server t-sql

考虑以下查询:

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);
Run Code Online (Sandbox Code Playgroud)

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

表“参数类型”。扫描计数 0,逻辑读取 2,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表 'Area'。扫描计数 0,逻辑读取 2,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表“参数”。扫描计数 1,逻辑读取 4,物理读取 0,预读读取 0,lob 逻辑读取 0,lob 物理读取 0,lob 预读读取 0。
表“工作表”。扫描计数 1,逻辑读 0,物理读 0,预读 0,lob 逻辑读 0,lob 物理读 0,lob 预读 0。

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

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

是否MERGE总是使用 tempdb?

BOL 中是否有任何内容可以解释这种行为?

在这种情况下使用INSERT&UPDATE会更快吗?

剩下

在此处输入图片说明

在此处输入图片说明

这是表结构

在此处输入图片说明

Jon*_*gel 8

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

如果没有对AreaIdand组合的唯一约束ParameterTypeId,给定的代码就会被破坏,因为它@UpdatedId = target.Id只会记录一行Id

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

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


Seb*_*ine 6

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

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

虽然我不知道您的查询是否是这种情况,因为我不知道索引定义,这很可能是这里发生的情况。