SQL Server 2008 R2的MERGE语句用于替代单独的INSERT和UPDATE语句的组合。

出于性能考虑,我们正在考虑更改保存数据的标准存储过程(将INSERT和UPDATE合并为单个存储过程):
ALTER PROCEDURE [dbo].[spCustomerSave]
    (
        @CustomerID int = null,
        @CustomerName nvarchar(50),
        @New_ID int output
    )
    AS
    BEGIN

    IF EXISTS(SELECT 1 FROM tblCustomer WHERE CustomerID = @CustomerID)
        BEGIN
            UPDATE tblCustomer
            SET 
                CustomerName = @CustomerName
            WHERE
                CustomerID = @CustomerID;
                SELECT @New_ID = @CustomerID;
        END
    ELSE
        BEGIN
            INSERT INTO tblCustomer(
                Taalnaam)
            VALUES(
                @CustomerName)
                SELECT @New_ID = scope_identity();
        END
    END
将其转换为使用MERGE语句的语法。
ALTER PROCEDURE [dbo].[spCustomerSave]
    (
        @CustomerID int = null,
        @CustomerName nvarchar(50),
        @New_ID int output
    )
    AS
    BEGIN

    SELECT @New_ID = @idTaal;

    MERGE dbo.tblCustomer as target
        USING (SELECT @CustomerID, @CustomerName) as source (CustomerID, CustomerName)
        ON (target.CustomerID = source.CustomerID)
        WHEN MATCHED THEN
            UPDATE SET 
                CustomerName = @CustomerName
        WHEN NOT MATCHED THEN
            INSERT (CustomerName)
            VALUES(source.CustomerName);
                SELECT @New_ID = scope_identity();
    END

问题:

  • 这样做会在性能方面对我们有益吗?(避免在主键上进行初始SELECT)

  • 这是MERGE语句的正确使用方式吗?大多数示例都显示MERGE语句用于执行多个DML操作的情况。

2个回答

我还没有对这两个进行过比较测试(但)也没有看到任何有关该主题的文章。Technet上有一篇关于优化MERGE语句性能的文章,但其中并没有包含与update/insert语法的比较。 然而,我可以提出一个改进你原本语法的建议,这将消除IF EXISTS的查找步骤。
UPDATE 
    dbo.tblCustomer
SET 
    CustomerName = @CustomerName
WHERE
    CustomerID = @CustomerID;

IF (@@ROWCOUNT = 1)
BEGIN
    SELECT @New_ID = @CustomerID;
END
ELSE
BEGIN
    INSERT 
        dbo.tblCustomer
        (Taalnaam)
    VALUES
        (@CustomerName);

    SELECT @New_ID = SCOPE_IDENTITY();
END
你可能也会对神话的破解:并发更新/插入解决方案感兴趣,其中包括一些MERGE使用的示例。

我怀疑你的表格必须非常庞大且索引不正确,或者有数百至数千个并发用户同时运行此过程(合并会使用1个较少的锁),才能真正看到这两个语句之间性能差异的任何形式。