Sql 为什么向现有列添加可为null的默认约束需要这么长时间?

Sql 为什么向现有列添加可为null的默认约束需要这么长时间?,sql,sql-server-2012,default-constraint,Sql,Sql Server 2012,Default Constraint,我有一个大约有4亿行的现有表。该表包括一组名为IsModified、IsDeleted和IsExpired的bit列 CREATE TABLE [dbo].[ActivityAccumulator]( [ActivityAccumulator_SK] [int] IDENTITY(1,1) NOT NULL, [ActivityAccumulatorPK1] [int] NULL, [UserPK1] [int] NULL, [Data] [varchar](51

我有一个大约有4亿行的现有表。该表包括一组名为IsModified、IsDeleted和IsExpired的
bit

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
值的地方,但我现在真的不需要这样做


仅尝试运行第一个
addconstraint
命令就已经执行了一个多小时了。考虑到我没有试图更改任何现有值,为什么需要这么长时间?

一种可能是服务器上有另一个进程正在锁定此表

假设我打开了两个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
请注意,在本例中,表的大小或复杂性是无关的;我被迫等待交易完成。只有通过
COMMIT
关闭事务或关闭会话1释放
Foo
上的锁,会话2中的alter指令才能完成

你怎么知道这是不是你的问题?查看SSMS活动监视器中的“流程”列表。如果您的
ALTER
指令正在等待其他操作完成,则“阻塞者”列中会有一个数字,指示导致您出现问题的命令的会话ID

该届会议可能会依次等待另一届会议,以此类推。如果您遵循这些参考,您最终会在“Head Blocker”列中找到一个进程,该进程具有
1
。从那里,您可以决定是否采取适当的行动来终止违规流程,或者只是等待它结束

  • 使用所有约束重新创建对象
  • 转储数据
  • 锁定原始对象
  • 切换对象名称

  • 如果你想优化、重新索引和避免像Dan提到的那样的冲突,这种方法是最快的。是的,对于这样的问题,我的第一个想法也是“死锁”。@Dan,+25似乎还不够。。。非常感谢。这正是问题所在。以前取消的查询仍在以终止/回滚状态运行。我非常关注所讨论的表的大小,甚至从未考虑过检查阻塞进程。大小并非完全无关:如果它是一个小表,回滚不会花费太长时间。是的。我想现在最好的办法就是等着看它能跑多久。。。不管怎样,我现在知道了我原来问题的答案。非常感谢。