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。
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 会更好,我更理解。