Bob*_*of4 15 sql-server-2005 sql-server alter-table
我有一个大型(约 6700 万行)名称-值表,该表在DataValue列上具有全文索引。
如果我尝试运行以下命令:
ALTER TABLE VisitorData ADD NumericValue bit DEFAULT 0 NOT NULL;
Run Code Online (Sandbox Code Playgroud)
它运行了 1 小时 10 分钟,但仍然无法在VisitorData包含约 6700 万行的表上完成。
以下是有关该表的更多详细信息:
CREATE TABLE [dbo].[VisitorData](
[VisitorID] [int] NOT NULL,
[DataName] [varchar](80) NOT NULL,
[DataValue] [nvarchar](3800) NOT NULL,
[EncryptedDataValue] [varbinary](max) NULL,
[VisitorDataID] [int] IDENTITY(1,1) NOT NULL,
CONSTRAINT [PK_VisitorData_VisitorDataID] PRIMARY KEY CLUSTERED (
[VisitorDataID] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY],
CONSTRAINT [UNQ_VisitorData_VisitorId_DataName] UNIQUE NONCLUSTERED (
[VisitorID] ASC,
[DataName] ASC
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[VisitorData]
ADD CONSTRAINT [UNQ_VisitorData_VisitorDataID] UNIQUE NONCLUSTERED (
[VisitorDataID] ASC
)
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF,
IGNORE_DUP_KEY = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON,
ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
ALTER TABLE [dbo].[VisitorData]
WITH CHECK ADD
CONSTRAINT [FK_VisitorData_Visitors] FOREIGN KEY([VisitorID])
REFERENCES [dbo].[Visitors] ([VisitorID])
GO
ALTER TABLE [dbo].[VisitorData]
CHECK CONSTRAINT [FK_VisitorData_Visitors] GO
CREATE FULLTEXT CATALOG DBName_VisitorData_Catalog WITH ACCENT_SENSITIVITY = ON
CREATE FULLTEXT INDEX ON VisitorData ( DataValue Language 1033 )
KEY INDEX UNQ_VisitorData_VisitorDataID
ON DBName_VisitorData_Catalog
WITH CHANGE_TRACKING AUTO
GO
Run Code Online (Sandbox Code Playgroud)
ALTER TABLE命令期间发生的等待类型是LCK_M_SCH_M(模式修改),根据以下查询结果:
select * from sys.dm_os_waiting_tasks
waiting_task_address session_id exec_context_id wait_duration_ms wait_type resource_address blocking_task_address blocking_session_id blocking_exec_context_id resource_description
-------------------- ---------- --------------- -------------------- -------------------- ------------------ --------------------- ------------------- ------------------------------- ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
0x0000000000B885C8 54 0 112695 LCK_M_SCH_M 0x00000000802DF600 0x000000000054E478 25 0 objectlock lockPartition=0 objid=834102012 subresource=FULL dbid=5 id=lock438a02e80 mode=IS associatedObjectId=834102012
0x0000000000B885C8 54 0 112695 LCK_M_SCH_M 0x00000000802DF600 0x00000000088AB048 23 0 objectlock lockPartition=0 objid=834102012 subresource=FULL dbid=5 id=lock438a02e80 mode=IS associatedObjectId=834102012
Run Code Online (Sandbox Code Playgroud)
我正在使用运行 SQL Server 2005 SP 2(即将升级到 2008 SP2)的生产服务器。
Jas*_*and 16
架构更改需要很长时间,因为您在更改期间为该列分配了一个默认值并使用不可为空的列强制执行该值,并且它必须为该列填充 60 多万行,这是一项非常昂贵的操作。我不确定您的应用程序要求是什么,但一种使架构更改更快的方法是将其添加为没有默认值的可为空的列,然后分批执行更新以将 0 指定为该列的值。更新完成后,您可以应用另一个架构更改以将列更改为不可为空并分配默认值。
全文索引可能与您的问题无关。在 SQL Server 2012 之前,这ADD COLUMN NOT NULL DEFAULT ...是一个离线操作,必须运行更新并使用新添加列的新默认值填充每一行。在 SQL Server 2012+ 中,操作速度要快得多,请参阅SQL Server 11 中添加值列的 Online non-NULL,因为它只更新表的元数据,实际上并不更新任何行。
ALTER TABLE由于更新,您的速度很可能很慢。请记住,由于这是一个单一的事务,因此将生成一个巨大的日志,并且您的日志现在可能正在增长,并且随着它的扩展而不断归零。但是,它也可能因为普通争用而变慢:语句可能无法获取表上的 SCH-M 锁。查看sys.dm_exec_requests应该显示如果是这种情况,wait_type和wait_resource列将指示ALTER语句是否被阻止或正在取得进展。