2014-09-05 5 views
10

У меня есть таблица с примерно 400 миллионами строк. Эта таблица включает набор столбцов bit с именем IsModified, IsDeleted и IsExpired.Почему добавление нулевого ограничения по умолчанию к существующему столбцу занимает так много времени?

CREATE TABLE [dbo].[ActivityAccumulator](
    [ActivityAccumulator_SK] [int] IDENTITY(1,1) NOT NULL, 
    [ActivityAccumulatorPK1] [int] NULL, 
    [UserPK1] [int] NULL, 
    [Data] [varchar](510) NULL, 
    [CoursePK1] [int] NULL, 
    [TimeStamp] [datetime] NULL, 
    [SessionID] [int] NULL, 
    [Status] [varchar](50) NULL, 
    [EventType] [varchar](40) NULL, 
    [DWCreated] [datetime] NULL, 
    [DWModified] [datetime] NULL, 
    [IsModified] [bit] NULL, 
    [DWDeleted] [datetime] NULL, 
    [IsDeleted] [bit] NULL, 
    [ActivityAccumulatorKey] [bigint] NULL, 
    [ContentPK1] [bigint] NULL 
) ON [PRIMARY] 

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

ALTER TABLE ActivityAccumulator 
ADD CONSTRAINT DF_ActivityAccumulatorIsExpired DEFAULT (0) FOR IsExpired 

ALTER TABLE ActivityAccumulator 
ADD CONSTRAINT DF_ActivityAccumulatorIsDeleted DEFAULT (0) FOR IsDeleted 

ALTER TABLE ActivityAccumulator 
ADD CONSTRAINT DF_ActivityAccumulatorIsModified DEFAULT (0) FOR IsModified 

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

Просто попытка запустить команду ADD CONSTRAINT выполняется уже более часа. Учитывая, что я не пытаюсь изменить какие-либо существующие ценности, почему это так долго?

ответ

5

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

Представьте меня есть два ВСС окна открыты, и в первом я выполнить следующие команды:

-- Session 1 
CREATE TABLE Foo(IsTrue BIT) 
INSERT INTO Foo VALUES (1),(1),(0) 
BEGIN TRANSACTION 
UPDATE Foo SET IsTrue = 1 - IsTrue 

А затем оставить окно SSMS открытым, так что сделка никогда не закрывается, пытаясь выполнить эту простую команду ограничения в других SSMS сессия будет висеть вечно:

-- Session 2 
ALTER TABLE Foo ADD CONSTRAINT FooDefault DEFAULT(0) FOR IsTrue 

Обратите внимание, что в этом примере, размер или сложность таблицы не имеет значения; Я вынужден дождаться завершения транзакции. Моя инструкция изменения в сеансе 2 не будет завершена до тех пор, пока я не отпущу блокировку на Foo либо на COMMIT сеанса транзакции или закрытия.

Как вы можете определить, является ли это вашей проблемой? Посмотрите список «Процессы» на мониторе активности SSMS. Если ваша команда ALTER ждет чего-то еще, в столбце «Заблокировано» появится номер, указывающий идентификатор сеанса команды, вызывающей вашу проблему.

SSMS Process list showing blocked process

Эта сессия может быть в свою очередь ждут на другой и так далее. Если вы следуете этим ссылкам, вы в конечном итоге найдете процесс с 1 в столбце «Блокировка заголовка». Оттуда вы можете решить, должно ли соответствующее действие убить процесс оскорбления или просто дождаться его.

+0

Да, для таких вопросов моя первая мысль также «тупиковая». – Ellesedil

+0

@Dan, +25 не кажется достаточно ... спасибо! Это точно описывает проблему. Ранее отмененный запрос все еще работает с состоянием KILLED/ROLLBACK.Я был настолько сосредоточен на размере рассматриваемой таблицы, что я даже не рассматривал проверку блокирующих процессов. – AHiggins

+0

Размер не совсем неуместен: если бы это был крошечный стол, то ROLLBACK не занимал бы столько времени. – Dan

0
  1. воссоздать объект со всеми ограничениями
  2. дамп данных
  3. запирают оригинальный объект
  4. переключатель имена объектов

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