Недавно я задал вопрос о том, как решить проблему в запросе tsql, который заставил меня использовать оператор MERGE. Это, однако, оказывается проблематичным, поскольку его производительность ужасна.
Что мне нужно сделать, так это вставить строки на основе набора результатов и сохранить идентификатор вставленной строки вместе с данными, из которых она получена (см. связанный вопрос).
Я закончил с таким запросом.
DECLARE @temp AS TABLE(
[action] NVARCHAR(20)
,[GlobalId] BIGINT
,[Personnumber] NVARCHAR(100)
,[Firstname] NVARCHAR(100)
,[Lastname] NVARCHAR(100)
);
;WITH person AS
(
SELECT top 1
t.[Personnumber]
,t.[Firstname]
,t.[Lastname]
FROM [temp].[RawRoles] t
WHERE t.Personnumber NOT IN
(
SELECT i.Account FROM [security].[Accounts] i
)
)
MERGE [security].[Identities] AS tar
USING person AS src
ON 0 = 1 -- all rows from src need to be inserted, ive already filtered out using CTE Query.
WHEN NOT MATCHED THEN
INSERT
(
[Created], [Updated]
)
VALUES
(
GETUTCDATE(), GETUTCDATE()
)
OUTPUT $action, inserted.GlobalId, src.[Personnumber], src.[Firstname], src.[Lastname] INTO @temp;
SELECT * FROM @temp
Используя этот запрос, я вставляю все строки, а затем сохраняю их во временной таблице вместе с исходными значениями для последующей обработки.
Это отлично работает на строках ниже 10 тыс. Но набор данных, с которым я это делаю, близок к 2 миллионам строк. Я выполнял этот запрос около часа без его завершения (в расширенной базе данных Azure премиум-уровня).
Вопрос: Как сделать это быстрее. Можно ли добиться такого же результата без слияния?
TOP 1
запроса неORDER BY
..? Что такое@sourceData
, поскольку это не определено в вашем SQL. - person Larnu   schedule 04.12.2019INSERT SELECT
, а не MERGE - person Panagiotis Kanavos   schedule 04.12.2019INSERT INTO Identities (...) OUTPUT inserted..... Select A,B C from RawRoles LEFT JOIN Accounts ON Account=PersonNumber Where Accounts.ID IS NULL
? - person Panagiotis Kanavos   schedule 04.12.2019NOT IN
с подзапросом. Если какая-либо возвращаемая строка имеет значениеNULL
, то поведение, которое вы получите, будет не таким, как вы ожидаете. Гораздо лучше использоватьNOT EXISTS
илиLEFT JOIN
и тестировать наNULL
. DB‹›Fiddle - person Larnu   schedule 04.12.2019MERGE
- это обходной путь для этого; поскольку он можетOUTPUT
получать данные из входных объектов. - person Larnu   schedule 04.12.2019