Недавно мне дали скрипт для обновления структуры базы данных на MS SQL Server. В нем было полно блоков, которые добавляли в таблицу столбец, заполняли его в существующих строках одинаковым значением и делали NOT NULL:
Создадим тестовую таблицу
При создании таблицы мы можем указать столбцу значение по умолчанию, которым оно будет заполнено при добавлении новой строки, если его значение не указано. Воспользуемся значеним по умолчанию и в ALTER TABLE:
Таким способом можно быстро "заполнять" значения новых столбцов не только константами, но результатом вызова функции, если он является константой времени выполнения команды. Например, для столбца типа datetime можно использовать функцию GETDATE:
Итак, пользователям MS SQL Server 2012 и более новых версий этой СУБД повезло. У них есть способ мгновенно заполнить новые столбцы таблицы значениями, независимо от количества строк в ней.
alter table MyTable add FIELD1 int null go update MyTable set FIELD1 = 1 go alter table MyTable alter column FIELD1 int not null goЧто будет, если количество строк в таблице измеряется не сотнями или тысячами, а миллионами или десятками миллионов?
Создадим тестовую таблицу
create table MyTable ( ID int identity, NAME varchar(50) not null, constraint PK_MyTable primary key (ID) ) goи зальем туда десять миллионов строк. На моем компьютере скрипт ALTER + UPDATE выполнялся примерно полминуты. Мне кажется, что это ужасно. Могу добавить, что в некоторые таблицы исходный скрипт добавлял несколько столбцов и делалось это отдельными блоками. То есть update изменяемой таблицы мог выполняться неоднократно.
При создании таблицы мы можем указать столбцу значение по умолчанию, которым оно будет заполнено при добавлении новой строки, если его значение не указано. Воспользуемся значеним по умолчанию и в ALTER TABLE:
alter table MyTable add FIELD1 int not null constraint DF_FIELD1 default 1 alter table MyTable drop constraint DF_FIELD1 goЭтот скрипт выполнил нужную задачу мгновенно! Дело в том, что, начиная с SQL Server 2012, существующие в таблице строки при такой операции не обновляются. Вместо обновления строк значение по умолчанию сохраняется в метаданных таблицы и используется, как значение не заполненного NOT NULL столбца. Значение по умолчанию, хранящееся в метаданных, будет перемещено в существующий столбец только при обновлении строки (даже если этот столбец не указан в UPDATE) и при перестройке таблицы или кластеризованного индекса. Для новых строк, если этот столбец не указан в INSERT, значение по умолчанию сразу сохраняется в столбце.
Таким способом можно быстро "заполнять" значения новых столбцов не только константами, но результатом вызова функции, если он является константой времени выполнения команды. Например, для столбца типа datetime можно использовать функцию GETDATE:
alter table MyTable add FIELD2 datetime not null constraint DF_FIELD2 default GETDATE()Примером функции у которой результат не является константой времени выполнения является NEWID. Она генерирует уникальное значение GUID для каждой строки. Использующий ее скрипт
alter table MyTable add FIELD3 uniqueidentifier not null constraint DF_FIELD3 default NEWID()выполняется у меня, аналогично первоначальному варианту с ALTER + UPDATE, примерно полминуты.
Итак, пользователям MS SQL Server 2012 и более новых версий этой СУБД повезло. У них есть способ мгновенно заполнить новые столбцы таблицы значениями, независимо от количества строк в ней.
Комментариев нет:
Отправить комментарий