Почему добавление нулевого ограничения по умолчанию в существующий столбец занимает так много времени?
У меня есть существующая таблица с примерно 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
выполняется уже более часа. Учитывая, что я не пытаюсь изменить какие-либо существующие значения, почему это так долго?
Ответы
Ответ 1
Возможно, у вас есть другой процесс на вашем сервере, который блокирует эту таблицу.
Представьте, что у меня открыто два SSMS-окна, и в первом я выполняю следующие команды:
-- 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
Обратите внимание, что в этом примере размер или сложность таблицы не имеет значения; Я вынужден дождаться завершения транзакции. Моя команда alter в сеансе 2 не будет завершена до тех пор, пока я не отпущу блокировку на Foo
либо COMMIT
транзакции или закрывающей сессии 1.
Как вы можете определить, является ли это вашей проблемой? Посмотрите список "Процессы" на мониторе активности SSMS. Если ваша команда ALTER
ожидает чего-то еще, то в столбце "Заблокировано" указывается номер сеанса команды, вызывающей вашу проблему.
![SSMS Process list showing blocked process]()
Эта сессия, в свою очередь, может ждать друг друга и т.д. Если вы следуете этим ссылкам, вы в конечном итоге найдете процесс с 1
в столбце "Блокировка заголовка". Оттуда вы можете решить, должно ли соответствующее действие убить процесс оскорбления или просто дождаться его.
Ответ 2
- воссоздайте объект со всеми ограничениями
- сбрасывать данные
- заблокировать исходный объект
- изменить имена объектов
этот способ является самым быстрым, если вы хотите оптимизировать, переиндексировать и избегать конфликтов, подобных тем, о которых говорил Dan