Как добавить столбец в большую таблицу SQL Server - PullRequest
22 голосов
/ 29 октября 2009

У меня есть производственная таблица SQL Server с миллионами строк, и получается, что мне нужно добавить в нее столбец. Или, чтобы быть более точным, мне нужно добавить поле к объекту, который представляет таблица.

Синтаксически это не проблема, и если бы в таблице не было так много строк и не было в работе, это было бы легко.

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

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

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

Ответы [ 6 ]

27 голосов
/ 29 октября 2009
ALTER TABLE table1 ADD
  newcolumn int NULL
GO

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

12 голосов
/ 29 октября 2009

Единственным реальным решением для непрерывной работы является резервирование .

Я признаю ответ @ Nestor о том, что добавление нового столбца в SQL Server не должно занимать много времени, но, тем не менее, это может быть простоем, что недопустимо в рабочей системе. Альтернативой является внесение изменений в параллельную систему, а затем после завершения операции замените новое на старое.

Например, если вам нужно добавить столбец, вы можете создать копию таблицы, затем добавить столбец к этой копии и затем использовать sp_rename(), чтобы переместить старую таблицу в сторону и новый стол на место.

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

Для некоторых видов сложных обновлений вы можете полностью дублировать базу данных на отдельном хосте сервера. Когда все будет готово, просто поменяйте записи DNS для двух серверов и вуаля!

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

7 голосов
/ 17 августа 2016

Я не хотел, чтобы столбец допускал пустые значения, что означало бы, что мне нужно иметь значение по умолчанию.

Добавление столбца NOT NULL с DEFAULT Ограничением к таблице с любым числом строк (даже миллиардов) стало намного проще, начиная с SQL Server 2012 (но только для Enterprise Edition), так как они позволили сделать это оперативной операцией (в большинстве случаев), где для существующих строк значение будет считываться из метаданных и фактически не сохраняться в строке до тех пор, пока строка не будет обновлена ​​или кластерный индекс не будет перестроен. Вместо того чтобы перефразировать, вот соответствующий раздел на странице MSDN для ALTER TABLE :

Добавление столбцов NOT NULL в качестве оперативной операции

Начиная с SQL Server 2012 Enterprise Edition, добавление столбца NOT NULL со значением по умолчанию является оперативной операцией, когда значением по умолчанию является постоянная времени выполнения . Это означает, что операция завершается практически мгновенно, независимо от количества строк в таблице. Это потому, что существующие строки в таблице не обновляются во время операции; вместо этого значение по умолчанию сохраняется только в метаданных таблицы, и значение ищется по мере необходимости в запросах, которые обращаются к этим строкам. Это поведение автоматическое; для реализации оперативной работы не требуется дополнительный синтаксис, кроме синтаксиса ADD COLUMN. Константа времени выполнения - это выражение, которое выдает одно и то же значение во время выполнения для каждой строки в таблице независимо от ее детерминизма. Например, константное выражение «Мои временные данные» или системная функция GETUTCDATETIME () являются константами времени выполнения. Напротив, функции NEWID () или NEWSEQUENTIALID () не являются константами времени выполнения, поскольку для каждой строки таблицы создается уникальное значение. Добавление столбца NOT NULL со значением по умолчанию, которое не является константой времени выполнения, всегда выполняется в автономном режиме, и на время операции получается эксклюзивная (SCH-M) блокировка.

Хотя существующие строки ссылаются на значение, хранящееся в метаданных, значение по умолчанию сохраняется в строке для всех новых вставляемых строк и не указывает другого значения для столбца. Значение по умолчанию, хранящееся в метаданных, перемещается в существующую строку при обновлении строки (даже если фактический столбец не указан в операторе UPDATE) или если таблица или кластерный индекс перестраивается.

Столбцы типа varchar (макс.), Nvarchar (макс.), Varbinary (макс.), Xml, текст, текст, изображение, иерархия, геометрия, география или CLR UDTS не могут быть добавлены в онлайн операция. Невозможно добавить столбец онлайн, если это приведет к тому, что максимально возможный размер строки превысит ограничение в 8 060 байт. В этом случае столбец добавляется как автономная операция.

7 голосов
/ 29 октября 2009

"Добавьте столбец, а затем выполните относительно небольшие пакеты ОБНОВЛЕНИЯ, чтобы заполнить столбец значением по умолчанию. Это должно предотвратить любые заметные замедления"

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

Возможно, вы захотите переименовать текущую таблицу из X в Y. Вы можете сделать это с помощью этой команды sp_RENAME '[OldTableName]', '[NewTableName]'.

Воссоздайте новую таблицу как X с новым столбцом, установленным на NOT NULL, а затем пакетной вставкой от Y до X и включите значение по умолчанию либо в вставку для нового столбца, либо поместив значение по умолчанию в новый столбец при повторном создании таблица X.

Я внес изменения такого типа в таблицу с сотнями миллионов строк. Это все еще заняло больше часа, но это не взорвало наш транс-журнал. Когда я попытался просто изменить столбец на NOT NULL со всеми данными в таблице, потребовалось более 20 часов, прежде чем я завершил процесс.

Вы тестировали, просто добавляя столбец, заполняя его данными и устанавливая для столбца значение NOT NULL?

Так что, в конце концов, я не думаю, что есть волшебная пуля.

3 голосов
/ 29 октября 2009

выберите в новую таблицу и переименуйте. Пример, добавление столбца i в таблицу A:

select *, 1 as i
into A_tmp
from A_tbl

//Add any indexes here

exec sp_rename 'A_tbl', 'A_old'
exec sp_rename 'A_tmp', 'A_tbl'

Должно быть быстрым и не затрагивать журнал транзакций, как при вставке в пакеты. (Я только что сделал это сегодня с таблицей строк в 70 миллионов за <2 минуты). </p>

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

0 голосов
/ 29 октября 2009

Другой метод заключается в добавлении столбца в новую связанную таблицу (допустим однозначное отношение, которое вы можете применить, задав FK уникальный индекс). Затем вы можете заполнить это партиями, а затем добавить объединение в эту таблицу, где бы вы ни хотели, чтобы данные отображались. Примечание. Я хотел бы рассмотреть это только для столбца, который я не хотел бы использовать в каждом запросе к исходной таблице, или если ширина записи в исходной таблице становилась слишком большой или если я добавлял несколько столбцов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...