添加外键约束会占用内存并导致分页

时间:2010-12-06 18:23:55

标签: tsql sql-server-2008-r2

我在为新创建的空表添加简单的外键约束时遇到很多问题。参考表是一个很小的参考表,其中有少于40个记录,但它被引用了很多。

这是发生了什么:新表成功创建,但是当添加FK约束时,它会“思考”很长时间并增加CPU负载。内存使用量增加,服务器开始像疯了一样分页并且没有响应(连接超时)。取消查询没有帮助。唯一有效的是重启服务器,这是非常昂贵的。

这是我正在尝试运行的脚本。我希望SQL服务器专家可以提供帮助。 THX!

USE [my_db]
GO

SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

CREATE TABLE [dbo].[MyNewTable](
    [Column1ID] [int] NOT NULL,
    [Column2ID] [int] NOT NULL
) ON [PRIMARY]

GO

ALTER TABLE [dbo].[MyNewTable]  WITH CHECK ADD  CONSTRAINT [FK_MyNewTable_Column1ID] FOREIGN KEY([Column1ID])
REFERENCES [dbo].[ReferenceTable] ([Column1ID])
ON UPDATE CASCADE
ON DELETE CASCADE
GO

ALTER TABLE [dbo].[MyNewTable] CHECK CONSTRAINT [FK_MyNewTable_Column1ID]
GO

编辑:ReferenceTable是一个小表,看起来像这样:

[Column1ID] [int] IDENTITY(1,1) NOT NULL,
[TxtCol1] [varchar](50) NOT NULL,
[TxtCol2] [varchar](50) NOT NULL,
[TxtCol3] [varchar](200) NOT NULL,
[TxtCol4] [nvarchar](2000) NOT NULL,
[TxtCol5] [varchar](200) NOT NULL,
[BitCol1] [bit] NOT NULL,
[TxtCol6] [varchar](200) NOT NULL,
[NumCol1] [smallint] NOT NULL,
[ExternalColumnId] [int] NOT NULL,
[NumCol2] [int] NOT NULL

Column1ID被其他表(FK)引用很多。 ExternalColumnId是另一个表的FK。在其中一个ALTER TABLE调用期间发生此问题。不幸的是,这些都是一起运行的,所以我无法说出哪一个引起了它。

编辑:一旦数据库进入“思考”模式,可以通过将其切换到单一模式然后再返回多用户模式来恢复它。它比重启服务器要好得多,但仍然不能接受。

4 个答案:

答案 0 :(得分:4)

随机想:你有没有打开任何交易?

ALTER TABLE将需要独占访问(与大多数DDL一样),它可能被模式锁阻塞,而模式锁又会阻止ReferenceTable,而后者又会阻止其他查询......

答案 1 :(得分:0)

我建议单独运行每个查询批处理。

首先,创建表并查看是否成功。

接下来,尝试使用WITH NOCHECK而不是WITH CHECK自行添加外键约束。在创建约束时,WITH NOCHECK将禁止在MyNewTable.Column1ID中对引用表的列中的值进行任何验证。如果MyNewTable为空或行数很少,我认为这不会产生太大影响,但我遇到过你所描述的症状 - 除了得到新约束的表中有数百万行

最后,运行最后一批尝试在新约束上设置WITH CHECK。如果这个陷入困境,您可能只需要保留新的FK集WITH NOCHECK,但不建议这样做,因为查询优化器会忽略定义的约束WITH NOCHECK,直到它们被设置回{{1 }}

答案 2 :(得分:0)

如果此问题可重现,我建议您打开Microsoft支持案例。可能是一个错误,你正在打它。如果发现这是一个已知问题,他们会向您退还打开案件的费用。

答案 3 :(得分:0)

需要研究的一些事情 - 不是解决方案,但它们可能会带来一些东西。

是否定义了任何触发器?

在创建新表时是使用还是访问数据库,还是空闲?

是否有任何事情(在部署或其他情况下)更新引用表中的Column1ID,或删除该表中的行?

引用表中的Column1ID是否存在主键或唯一约束? (你没有列出一个,但我认为如果没有SQL,SQL会立即失败。)