SQL Server достаточно умен, чтобы не выполнять ввод-вывод, когда он на самом деле не нужен? - PullRequest
1 голос
/ 02 сентября 2011

Скажем, у меня есть оператор слияния, который выглядит следующим образом:

merge TableA as target
using (select Id, Description, UnitCost
       from   TableB) 
       as source (Id, Description, UnitCost)
on (target.Id = source.Id)             
when MATCHED then
    update set Id = source.Id, 
               Description = source.Description, 
               UnitCost = Source.UnitCost
when NOT MATCHED then
    insert (Id, Description, UnitCost)
    values (source.Id, source.Description, source.UnitCost);

Когда я запускаю это, он говорит мне, сколько строк было затронуто. Если я запускаю его и знаю, что источник и пункт назначения одинаковы, я все равно получаю сообщение о том, что было затронуто количество строк x. В моем случае это около 200 строк. SQL Server перезаписывает те же данные на диск?

200 строк - ничто и их легко переписать, не влияя на производительность SQL Server. Но если у меня есть оператор слияния с 500 000+ строками и множеством индексов, то повторное обновление всех данных в таблице будет дорогостоящим.

Нужно ли проверять, что данные изменились первыми (по крайней мере, в тех случаях, когда производительность могла быть проблемой)?

Если это так, как мне это сделать в операторе слияния (возможно, используя мой пример выше)?

Ответы [ 2 ]

2 голосов
/ 02 сентября 2011

SQL Server и любой механизм, основанный на записи журнала в пул буферных пулов, не будут выполнять ввод / вывод данных для обновлений / удалений / вставок. Так было всегда с момента публикации статьи ARIES , и почти все современные реляционные базы данных ведут свое происхождение от System-R и ARIES.

Когда строка обновляется (и включает в себя вставку и удаление строки), запись журнала добавляется в буфер журнала в памяти, описывающий изменение, затем страница, содержащая строку в памяти, обновляется. На диск ничего не записано. Исполнение продолжается. Когда транзакция фиксируется, генерируется новая запись журнала, и фиксация не может быть продолжена до тех пор, пока вся запись в памяти, вплоть до записи фиксации журнала включительно, не будет записана на диск. Это единственный обязательный ввод-вывод, который требуется для продолжения обновления. Если вы обновите 500 тыс. Строк, то в одном операторе система будет ждать только сброса журнала после . Все 500 тыс. Строк были обновлены.

Данные в памяти периодически записываются на диск во время проверки .

2 голосов
/ 02 сентября 2011
merge TableA as target
using (select Id, Description, UnitCost
       from   TableB) 
       as source (Id, Description, UnitCost)
on (target.Id = source.Id)             
when MATCHED AND (ID <> source.ID OR Description <> source.Description OR UnitCost <> Source.UnitCost) then
    update set Id = source.Id, 
               Description = source.Description, 
               UnitCost = Source.UnitCost
when NOT MATCHED then
    insert (Id, Description, UnitCost)
    values (source.Id, source.Description, source.UnitCost);

Вы можете добавить условие условного поиска в оператор Matched, это в основном проверяет, что что-то действительно изменилось. Не уверен, будет ли это обязательно быстрее, но он не будет обновлять строки, которые не нужно обновлять.

Если вам нужна дополнительная информация, проверьте документы MERGE (T-SQL)

...