Добавление столбцов в производственные таблицы

28

Каков наилучший способ добавления столбцов в большие производственные таблицы в SQL Server 2008 R2? Согласно книгам Microsoft в Интернете:

Изменения, указанные в ALTER TABLE, применяются немедленно. Если изменения требуют изменения строк в таблице, ALTER TABLE обновляет строки. ALTER TABLE получает блокировку изменения схемы для таблицы, чтобы убедиться, что никакие другие соединения не ссылаются даже на метаданные таблицы во время изменения, за исключением операций с индексами в сети, которые требуют очень короткой блокировки SCH-M в конце.

(Http://msdn.microsoft.com/en-us/library/ms190273.aspx)

На большой таблице с миллионами строк это может занять некоторое время. Является ли отключение единственным вариантом? Какой лучший способ справиться с такой ситуацией?

ш-бета
источник
1
Недавняя статья, касающаяся этой проблемы: sqlservercentral.com/articles/Change+Tracking/74397
8kb

Ответы:

27

"Это зависит"

Если вы добавляете столбец, который не требует добавления данных в строки, то это может быть довольно быстро.

Например, добавление int или char требует физических движений строк. Добавлять обнуляемый varchar без значения по умолчанию не следует (если только растровое изображение NULL не нужно расширять)

Вы должны попробовать это на восстановленной копии производства, чтобы получить оценку

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

Я изменил миллиард таблиц строк, которые заняли несколько секунд, чтобы добавить обнуляемый столбец.

Я сказал, чтобы сначала сделать резервную копию?

ГБН
источник
2
+1 на резервную копию. и убедитесь, что у вас есть достаточно места для журнала тоже.
SqlACID
Можете ли вы объяснить, почему добавление типа int или char требует физических движений строк?
sh-beta
5
Вы имели в виду «не» требует добавления данных в строки во второй строке?
Бен Брока
21

Если столбец NULLable, влияние должно быть незначительным. Если столбец не может быть НЕДЕЙСТВИТЕЛЕН, и значение должно быть установлено, тогда оно может быть совершенно другим. В этом случае я бы вместо добавления ненулевого ограничения и ограничения по умолчанию в одном кадре эффективно добавил данные в каждую строку:

  • добавить столбец как NULLable - в большинстве случаев должен быть быстрым
  • обновить значения по умолчанию
    • Вы можете сделать это партиями, если это необходимо
    • Вы также можете использовать это, чтобы применить условную логику, где некоторые строки могут не получить значение по умолчанию
  • добавить ненулевые ограничения / ограничения по умолчанию
    • это будет быстрее, когда ни один из данных не равен NULL, но все равно должен быть измеримым

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

Аарон Бертран
источник
•add the not null/default constraintsНапоследок : я не уверен, что с этим нет потенциальной проблемы ... Когда MSSQL (даже 2008R2) меняет ненулевой столбец на нулевой, если вы добавите трассировку, вы сможете увидеть ее на самом деле под прикрытием делать полное обновление каждой строки таблицы, то есть update table1 set column1 = column1я предполагаю, что она выполняет ненулевую проверку совершенно идиотским способом. Эта транзакция в два раза больше таблицы (до и после страниц), поэтому для таблицы DW может быть огромной. Ранее мы должны были скопировать данные,
Если кто-нибудь знает способ обойти это, я хотел бы знать ... В отличие от этого, в Oracle изменение нулевого значения на ненулевое блокирует, затем выбор для проверки отсутствия ненулевых значений, а затем мгновенное обновление чисто метаданных.
Эй, Майк, это звучит как хороший потенциальный вопрос сам по себе.
Дерек Дауни
4

Рассматривали ли вы:

  1. Создание новой таблицы, которая включает в себя изменения в определении таблицы.
  2. Вставка в определение новой таблицы, выбирая из исходной таблицы.
  3. Переименование исходной таблицы в _orig, а затем переименование новой таблицы в исходное имя таблицы.

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

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

RobPaller
источник
Разве вам не нужна блокировка записи вместо чтения? Для пользователей хорошо видеть данные в старой таблице, вы просто не хотите, чтобы они вносили какие-либо изменения, которые будут перезаписаны, когда вы закончите замену буфера.
Джон на все руки
Я думал о том, где немного проще контролировать изменения. В ситуации OLTP вы правы, блокировка записи была бы необходима, чтобы избежать внесения изменений в таблицу.
RobPaller