2013-11-12 3 views
15

Мне нужно добавить новый столбец в таблицу в моей базе данных. В таблице содержится около 140 миллионов строк, и я не уверен, как действовать без блокировки базы данных.Добавить новый столбец в таблицу большой базы данных

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

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

Я действительно ценю некоторые прямые ответы на этот вопрос. Это выполнимо или нет?

+0

У вас есть окна с низкой нагрузкой? –

+0

Хотите, чтобы отдых таблицы с 'create as select' был быстрее? мы используем этот подход для оракула db. вам тогда нужно воссоздать все ограничения. – alko

+0

Какую версию SQL Server вы используете? Если 2012, пожалуйста, укажите текущее определение таблицы и подробную информацию о новом столбце, который вы добавляете. –

ответ

9

Да, это в высшей степени выполнимо.

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

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

Как это работает вообще:

+---------------------+------------------------+-----------------------+ 
| Column is Nullable? | Default Value Supplied | Result    | 
+---------------------+------------------------+-----------------------+ 
| Yes     | No      | Quick Add (caveat) | 
| Yes     | Yes     | Long running lock  | 
| No     | No      | Error     | 
| No     | Yes     | Long running lock  | 
+---------------------+------------------------+-----------------------+ 

Оговоркой бит:

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

Редактировать -> @MartinSmith указал, что растровое изображение NULL будет расширяться только при изменении строки, большое спасибо. Однако, как он также указывает, если размер строки расширяется за пределы байта 8060 в SQL Server 2012, то a long running lock may still be required. Большое спасибо * 2.

Второй нюанс:

Попробуй.

Третий и последний нюанс:

Нет уж, проверить его.

+1

Только метаданные Yep изменяются, и 'NULL_BITMAP' не будет расширяться до следующего обновления строки. –

+0

@MartinSmith - Я хотел бы работать с вами однажды. :) Спасибо и большое уважение. –

+0

Спасибо! [Хотя я только что вспомнил, что ситуация немного изменилась в 2012 году) (http://rusanu.com/2012/02/16/adding-a-nullable-column-can-update-the-entire-table/) –

6

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

USE [MyDB] 
GO 

ALTER TABLE [dbo].[Customer] ADD [CustomerTypeId] TINYINT NULL 
GO 
ALTER TABLE [dbo].[Customer] ADD CONSTRAINT [DF_Customer_CustomerTypeId] DEFAULT 1 FOR [CustomerTypeId] 
GO 
DECLARE @batchSize bigint = 5000 
    ,@rowcount int 
    ,@MaxID int; 

SET @rowcount = 1 
SET @MaxID = 0 

WHILE @rowcount > 0 
BEGIN 
    ;WITH upd as (
     SELECT TOP (@batchSize) 
      [ID] 
      ,[CustomerTypeId] 
     FROM [dbo].[Customer] (NOLOCK) 
     WHERE [CustomerTypeId] IS NULL 
      AND [ID] > @MaxID 
     ORDER BY [ID]) 

    UPDATE upd 
      SET [CustomerTypeId] = 1 
       ,@MaxID = CASE WHEN [ID] > @MaxID THEN [ID] ELSE @MaxID END 

    SET @rowcount = @@ROWCOUNT 
    WAITFOR DELAY '00:00:01' 
END; 

ALTER TABLE [dbo].[Customer] ALTER COLUMN [CustomerTypeId] TINYINT NOT NULL; 
GO 

ALTER TABLE [dbo].[Customer] ADD [CustomerTypeId] TINYINT NULL изменения только метаданных (Sch-M замки) и время блокировки не зависит от количества строк в таблице

После этого я заполняю новый столбец по умолчанию небольшими порциями (5000 строк). Я жду одну секунду после каждого цикла, чтобы не блокировать таблицу слишком агрессивно. У меня есть ИНТ столбец «ID» в качестве первичного кластерном ключ

Наконец, когда все новый столбец заполнен меняю его NOT NULL

+1

. Вы должны описать, пытаются решить. (Я могу вывести его из чтения кода, но он не obvoius для случайного читателя.) –

+1

Исправлено, спасибо @ KlasLindbäck – AlexK

1

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

+0

с 140 миллионами строк, которые не будут гладкими – zencv

+0

@zencv: Я проделал эту технику с 30-40 миллионами, но вы правы, нужно какое-то особое отношение с 140 muillion – Suleman

5

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

Вы не должны беспокоиться об операциях сами, потому что SQL Server делает все правильно:

использует компонент Database Engine модификация схемы (Sch-M) блокируется во время языка определения данных в таблицы (DDL) например, добавление столбца или отбрасывание таблицы. За время, которое удерживается, замок Sch-M предотвращает параллельный доступ к таблице. Это означает, что замок Sch-M блокирует все внешние операции до тех пор, пока замок не будет отпущен.

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

EDIT:

Here Вы можете найти более подробную информацию о вашем вопросе. Как правило, Matt Whitfield правильно и

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

и когда

Новая колонка обнуляемая с NULL по умолчанию. Метаданные таблицы записывают тот факт, что новый столбец существует, но не может быть в записи . Вот почему нулевая битовая карта также имеет количество столбцов в этой конкретной записи. SQL Server может решить, присутствует ли столбец в записи. Итак - это НЕ операция размера данных - существующие записи таблицы не обновляются при добавлении нового столбца. Записи будут обновляться только тогда, когда обновляются для некоторых других операций.

+0

Это редактирование делает все ясно. SQL Server, очевидно, не волнует, имеет ли значение значение NULL (нет необходимости в пересчете), он принимает только новый столбец, если столбец изменен после его добавления? – FREDRIK

+0

Да, похоже. Но если вы проверите ссылку, предоставленную «Мартином Смитом», вы увидите, что есть исключение. Я не знаком с описанной там ситуацией, но, как я читал, я полагаю, что лучше всего сделать следующее: 1. Создать таблицу на вашей локальной машине; 2. Добавьте некоторые записи; 3. Измените таблицу, добавив новый столбец; 4. Проверьте, появится ли ситуация из ссылки; – gotqn

+0

Да, я сделаю некоторое тестирование перед тем, как выполнить производственную базу данных, конечно. Но, как я понял, это было только для SQL Server 2012 (по тому, что он написал, я не могу получить доступ к ссылке по какой-то причине)? Я в настоящее время работает 2008. – FREDRIK

Смежные вопросы