Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 улучшение MERGE запроса  [new]
Idol_111
Member

Откуда:
Сообщений: 605
Прочитал недавно статью Бен-Гана в последнем номере SQL Server Pro про MERGE и решил поулучшать некоторые свои скрипты.
Один из скриптов "поставил" меня в тупик :).

Был скрипт типа:
MERGE INTO dbo.positions AS tgt
USING 
#TmpPositions
ON #TmpPositions.PositionNumber = TGT.PositionNumber
and #TmpPositions.PositionAsAtDate = TGT.PositionAsAtDate 
WHEN MATCHED 
THEN UPDATE
SET tgt.[PositionNumber]              = #TmpPositions.[PositionNumber]
	, tgt.[IsUnlisted]                = #TmpPositions.[IsUnlisted]
	, tgt.[IsYieldOverridden]         = #TmpPositions.[IsYieldOverridden]
	, tgt.[PositionAsAtDate]          = #TmpPositions.[PositionAsAtDate]
WHEN NOT MATCHED 
THEN INSERT
([PositionNumber],[IsUnlisted],[IsYieldOverridden],[PositionAsAtDate])
values (#TmpPositions.[PositionNumber],#TmpPositions.[IsUnlisted],#TmpPositions.[IsYieldOverridden],#TmpPositions.[PositionAsAtDate])
when not matched by source 
		and trg.PositionAsAtDate in (select distinct PositionAsAtDate from #TmpPositions)
then delete
;

Решил обойтись без временной таблицы (как Айзек советовал, в принципе действительно получаете быстрее раза в два в моих случаях), однако существует ограничение на использование данных из Источника в условие when not matched by source. Т.е. написать что-то типа этого не получается:
MERGE INTO dbo.positions AS tgt
USING 
OPENROWSET(BULK '\\server\positions_cut.txt',
FORMATFILE = '\\server\positions.fmt'
,FIRSTROW = 2) AS src
ON SRC.PositionNumber = TGT.PositionNumber
and SRC.PositionAsAtDate = TGT.PositionAsAtDate 
WHEN MATCHED 
THEN UPDATE
SET tgt.[PositionNumber]              = src.[PositionNumber]
	, tgt.[IsUnlisted]                = src.[IsUnlisted]
	, tgt.[IsYieldOverridden]         = src.[IsYieldOverridden]
	, tgt.[PositionAsAtDate]          = src.[PositionAsAtDate]
WHEN NOT MATCHED 
THEN INSERT
([PositionNumber],[IsUnlisted],[IsYieldOverridden],[PositionAsAtDate])
values (src.[PositionNumber],src.[IsUnlisted],src.[IsYieldOverridden],src.[PositionAsAtDate])
when not matched by source 
		and trg.PositionAsAtDate in (select distinct PositionAsAtDate from src)
then delete
;

Нельзя использовать select distinct PositionAsAtDate from src.

Может у кого будут мысли, как это можно обойти?
Заранее спасибо.
5 сен 12, 04:55    [13114740]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
aleks2
Guest
Изучить кляузу with.
5 сен 12, 06:01    [13114748]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
Idol_111
Member

Откуда:
Сообщений: 605
aleks2
Изучить кляузу with.

Не уловил Вашей мысли.
Если Вы имеете ввиду вынести OPENROWSET под WITH, так это тоже работать не будет по выше изложенной причине.
Если что-то еще, то уж пожалуйста объясните заблудшему. :)
5 сен 12, 06:21    [13114759]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
aleks2
Guest
Idol_111
aleks2
Изучить кляузу with.

Не уловил Вашей мысли.
Если Вы имеете ввиду вынести OPENROWSET под WITH, так это тоже работать не будет по выше изложенной причине.
Если что-то еще, то уж пожалуйста объясните заблудшему. :)


Ну, если ты уже пробовал... хе-хе. Но у мя подозрение, что нет.
5 сен 12, 06:23    [13114761]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
Idol_111
Member

Откуда:
Сообщений: 605
aleks2,
Уже попробовал, будь уверен :).
5 сен 12, 06:41    [13114773]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
Idol_111
Member

Откуда:
Сообщений: 605
Вот так:
;with src as
(
select *
from OPENROWSET(BULK '\\server\positions_cut.txt',
FORMATFILE = '\\server\positions.fmt'
,FIRSTROW = 2) AS bsrc
)
MERGE INTO dbo.positions AS tgt
USING src
ON SRC.PositionNumber = TGT.PositionNumber
and SRC.PositionAsAtDate = TGT.PositionAsAtDate 
WHEN MATCHED 
THEN UPDATE
SET tgt.[PositionNumber]              = src.[PositionNumber]
	, tgt.[IsUnlisted]                = src.[IsUnlisted]
	, tgt.[IsYieldOverridden]         = src.[IsYieldOverridden]
	, tgt.[PositionAsAtDate]          = src.[PositionAsAtDate]
WHEN NOT MATCHED 
THEN INSERT
([PositionNumber],[IsUnlisted],[IsYieldOverridden],[PositionAsAtDate])
values (src.[PositionNumber],src.[IsUnlisted],src.[IsYieldOverridden],src.[PositionAsAtDate])
when not matched by source 
		and trg.PositionAsAtDate in (select distinct PositionAsAtDate from src)
then delete
;
5 сен 12, 06:43    [13114775]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
aleks2
Guest
А типерь подробнее, что тя не устраивает?

;with src as
(
select *
from OPENROWSET(BULK '\\server\positions_cut.txt',
FORMATFILE = '\\server\positions.fmt'
,FIRSTROW = 2) AS bsrc
)
, cond as (select distinct PositionAsAtDate from src)
MERGE INTO dbo.positions AS tgt
USING src
ON SRC.PositionNumber = TGT.PositionNumber
and SRC.PositionAsAtDate = TGT.PositionAsAtDate 
WHEN MATCHED 
THEN UPDATE
SET tgt.[PositionNumber]              = src.[PositionNumber]
	, tgt.[IsUnlisted]                = src.[IsUnlisted]
	, tgt.[IsYieldOverridden]         = src.[IsYieldOverridden]
	, tgt.[PositionAsAtDate]          = src.[PositionAsAtDate]
WHEN NOT MATCHED 
THEN INSERT
([PositionNumber],[IsUnlisted],[IsYieldOverridden],[PositionAsAtDate])
values (src.[PositionNumber],src.[IsUnlisted],src.[IsYieldOverridden],src.[PositionAsAtDate])
when not matched by source 
		and trg.PositionAsAtDate in (select PositionAsAtDate from cond)
then delete
;
5 сен 12, 08:37    [13114942]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
Idol_111
Member

Откуда:
Сообщений: 605
aleks2,
Извиняюсь, лоханулся, и первый вариант был рабочий. Накосячил в синтаксисе при реальной проверке.

Только похоже в этом случае выигрыш от подобного изменения проподает. Это я уже проверю позже.

Всегда говорил две головы лучше, чем одна :).
Спасибо за помощь.
5 сен 12, 09:07    [13115115]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
aleks2
Guest
Idol_111
aleks2,
Только похоже в этом случае выигрыш от подобного изменения проподает.


Если вам БЫСТРО - альтернативы временной таблице нету. Только ДВЕ временные таблицы и индексы на них.

declare @t table(PositionAsAtDate ... primary key clustered);
insert @t
select distinct PositionAsAtDate from #TmpPositions;

MERGE INTO dbo.positions AS tgt
USING 
#TmpPositions
ON #TmpPositions.PositionNumber = TGT.PositionNumber
and #TmpPositions.PositionAsAtDate = TGT.PositionAsAtDate 
WHEN MATCHED 
THEN UPDATE
SET tgt.[PositionNumber]              = #TmpPositions.[PositionNumber]
	, tgt.[IsUnlisted]                = #TmpPositions.[IsUnlisted]
	, tgt.[IsYieldOverridden]         = #TmpPositions.[IsYieldOverridden]
	, tgt.[PositionAsAtDate]          = #TmpPositions.[PositionAsAtDate]
WHEN NOT MATCHED 
THEN INSERT
([PositionNumber],[IsUnlisted],[IsYieldOverridden],[PositionAsAtDate])
values (#TmpPositions.[PositionNumber],#TmpPositions.[IsUnlisted],#TmpPositions.[IsYieldOverridden],#TmpPositions.[PositionAsAtDate])
when not matched by source 
		and trg.PositionAsAtDate in (select PositionAsAtDate from @t)
then delete
;
5 сен 12, 09:20    [13115204]     Ответить | Цитировать Сообщить модератору
 Re: улучшение MERGE запроса  [new]
Idol_111
Member

Откуда:
Сообщений: 605
тестирование показало, что смысла переделывать нет.
В моем случае, где целевая таблица в несколько десятков миллионов строк, потери идут на целевой таблице и не суть важно есть индексы во временной или нет (где только сотни тысяч строк).

aleks2 еще раз спасибо за обсуждение.
6 сен 12, 00:46    [13121326]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить