Как добавить столбец версии строки в большую таблицу с минимальным временем простоя

21

Используя SQL Server 2008 и более поздние версии, я хочу добавить столбец rowversion в большую таблицу, однако, когда я просто

ALTER TABLE [Tablename]
ADD Rowversion [Rowversion] NOT NULL

Тогда таблица будет недоступна для обновления слишком долго.

Какие стратегии я могу использовать, чтобы уменьшить это время простоя? Я все рассмотрю. Чем проще, тем лучше, но я рассмотрю любую стратегию.

Я думаю, что в качестве последнего средства я мог бы сохранить промежуточную таблицу копирования, поддерживаемую триггерами, а затем sp_rename промежуточной таблицы в исходную таблицу. Но я надеюсь на что-то более простое.

Майкл Дж Сварт
источник

Ответы:

26

Подумайте о создании новой таблицы с той же схемой и столбцом версии строки и добавьте представление поверх обеих таблиц, которое объединяет все. Попросите людей использовать представление и написать вместо триггеров соответствующие таблицы и представления.

Вставки должны отправляться в новую таблицу, обновления должны перемещать данные в новую таблицу, а удаления должны применяться к обеим таблицам.

Затем выполните групповые перемещения в фоновом режиме, перемещая столько записей за раз, сколько сможете, к новой таблице. У вас все еще могут быть проблемы с параллелизмом, пока это происходит, и некоторые дурацкие планы выполнения, но это позволяет вам оставаться в сети, пока происходят движения.

В идеале вы должны начать процесс в пятницу днем, чтобы минимизировать влияние на конечных пользователей, и попытаться выполнить его до утра понедельника. Как только это будет на месте, вы можете изменить представление так, чтобы оно указывало только на новую таблицу, и планы выполнения дерьма исчезли. Идеально.

Чтобы избежать срабатывания триггеров при переносе данных в пакетах, посмотрите на количество строк в удаленных / вставленных таблицах в триггере и пропустите действия, если они близки к числу строк в вашем пакете.


В конце концов Майкл решил пропустить представление (а не удалять из исходной таблицы), чтобы получить более стабильные планы. Компромисс держал в основном две копии таблицы. Он превратил это в серию постов в блоге .

Брент Озар
источник
7

Если у вас есть время для планирования, есть гораздо более простое решение ... (обычно)

Длинные блокировки почти наверняка вызваны разделением страниц на уровне хранилища. Так что заставляйте их по собственному графику.

  1. Добавьте NULL-способный временный столбец с типом данных VARBINARY(8).
  2. Найдите свободное время в базе данных, чтобы обновить партии существующих записей, указав допустимое значение для поля. ( 0x0000000027F95A5Bнапример)
  3. Обновления приведут к необходимому разделению страниц и выделят больше места для таблицы.
  4. Когда вы пойманы, удалите временный столбец (не касается выделенного хранилища) и добавьте столбец rowversion.
  5. Отсутствие разбиения страницы и блокировка, необходимая только для заполнения значений.

Я успешно использовал это, чтобы добавить столбец версии строки в таблицу строк размером 150M менее чем за 10 минут.

Предостережение ... если у вас есть таблица с большими полями varchar (особенно varchar(max)), SQL Server решает перестроить таблицу вместо повторного использования нового доступного пространства. Все еще пытаюсь найти способ обойти это.

Скотт Линч
источник
Интересно, я не уточнил, что означало «слишком долго» в моем вопросе. Если> 30 минут слишком долго для вашего сценария и 10 минут допустимы, это решение будет работать. Мой сценарий включал попытки достичь нулевого времени простоя или, более конкретно, <10 секунд, что достигается ответом Брента.
Майкл Дж Сварт
1

Если TIMESTAMPвы добавляете это NULLABLE:

  1. Добавить VARBINARY(8)столбец
  2. Заполните данными.

После того, как она населена, в спина к спине заявления SQL, столбец вы только что добавили и заселена, и добавить столбец.DROPVARBINARY(8)TIMESTAMP NULL


Если TIMESTAMPвы добавляете это NOT NULLABLE:

  1. Добавить BINARY(8)столбец
  2. Заполните данными.

После того, как она населена, в спина к спине заявления SQL, столбец вы только что добавили и малонаселенных и столбец.DROPBINARY(8)ADD THE TIMESTAMP NOT NULL

Пол Уайт говорит, что GoFundMonica
источник