这个 MERGE 语句中的更新是多余的吗?

Dan*_*ars 2 sql-server t-sql sql-server-2008-r2 merge

我正在尝试提高复杂存储过程的性能。存储过程内部是以下MERGE语句。我对MERGE语法不是很熟悉。

[Contact].[PhoneNumber]表如下所示:

CREATE TABLE [Contact].[PhoneNumber]
(
    [Id] [int] IDENTITY(1,1) NOT NULL PRIMARY KEY,
    [PhoneNumber] [nvarchar](255) NOT NULL
    [InsertedAtDateTimeUTC] [datetime2](7) NOT NULL DEFAULT(sysutcdatetime())
)
Run Code Online (Sandbox Code Playgroud)

合并看起来像这样:

;WITH _ContactPhoneNumbers ([PhoneNumber]) AS 
(
    SELECT DISTINCT ([#ChannelData].[CallerAni])
    FROM [#ChannelData]
)
MERGE [Contact].[PhoneNumber] WITH (HOLDLOCK) _target
USING [_ContactPhoneNumbers] _source ON [_target].[PhoneNumber] = [_source].[PhoneNumber]

WHEN NOT MATCHED THEN
    INSERT ([PhoneNumber])
    VALUES ([PhoneNumber])

WHEN MATCHED THEN
    UPDATE 
        SET [_target].[PhoneNumber] = [_source].[PhoneNumber]
        OUTPUT INSERTED.[Id], [_source].[PhoneNumber] INTO #Contact_PhoneNumber_Output ([Id], [PhoneNumber]);   
Run Code Online (Sandbox Code Playgroud)

我把它读为:

如果表PhoneNumber中不存在 ,则[Contact].[PhoneNumber]合并会在 中插入一个新行[Contact].[PhoneNumber]并返回新的Id。如果PhoneNumber确实存在,则合并将更新为PhoneNumber相同的值,并返回Id现有行的 。

UPDATE多余的吗?

如果它是多余的,我会把它拿出来看看它是否能提高性能。MERGE存储过程中有几个语句遵循相同的模式(使用UPDATE),因此它可能是一个有用的增益。

Id返回即使它的存在,因为它是用来作为进一步插入的FK。

Dan*_*ars 5

WHEN MATCHED THEN子句中需要有一些东西,否则Id当行存在时你不会得到返回。

但是,您不需要更新目标表

DECLARE @dummy int;

;WITH    _ContactPhoneNumbers ( [PhoneNumber] )
              AS ( SELECT    DISTINCT
                            ( [#ChannelData].[CallerAni] )

                   FROM     [#ChannelData]
                 )
        MERGE [PhoneNumber]  WITH ( HOLDLOCK ) _target
        USING [_ContactPhoneNumbers] _source
        ON [_target].[PhoneNumber] = [_source].[PhoneNumber]
        WHEN NOT MATCHED THEN
            INSERT ( [PhoneNumber] )
            VALUES ([PhoneNumber] )
        WHEN MATCHED THEN
            UPDATE SET @dummy = 0
        OUTPUT
            INSERTED.[Id] ,                
            [_source].[PhoneNumber]
        INTO #Contact_PhoneNumber_Output ( [Id], [PhoneNumber] );
Run Code Online (Sandbox Code Playgroud)

鉴于使用 SQL Server 的 MERGE 语句中的注意事项中的信息,我将MERGE完全放弃。也有很多LCK_M_RS_U争用,所以我认为使用更简单的 SQL 会更好,我更理解。