我有一个包含许多约束的庞大数据库,我已经更新了一些数据禁用约束,我只是想重新启用它们。
我使用了以下查询
EXEC sp_msforeachtable 'ALTER TABLE MyTable NOCHECK CONSTRAINT all'
exec sp_msforeachtable @command1='print ''MyTable''', @command2='ALTER TABLE MyTable WITH CHECK CHECK CONSTRAINT all'
但是当我运行启用查询时,由于数据量巨大,需要很长时间。这需要1个多小时。
我只想以正确的方式快速启用它而不会出现任何问题。
请指导我如何克服这个问题。
答案 0 :(得分:2)
“没有任何问题的正确方式”这样做需要时间。您可以通过省略WITH CHECK
选项来提高速度,但最终会在数据库中使用untrusted constraints,因此我不建议使用该选项。
答案 1 :(得分:1)
使用sp_msforeachtable运行语句顺序。最有可能通过几个线程传播的东西将加速这个过程。使用Service Broker,可以在SQL代码中完成。
(下面是从内存中编写的代码,我没有可用于测试它的SQL Server。因此可能存在一些错误。每当我有服务器可用时,我都会更新。)
首先创建激活程序
CREATE PROC p_enable_constraints
AS
DECLARE @handle UNIQUEIDENTIFIER
, @message sysname
, @sql nvarchar(max)
WHILE 1=1
BEGIN
BEGIN TRAN
WAITFOR ( RECEIVE TOP(1) @handle = conversation_handle,
@message = message_body
FROM ConstraintQueueReceive), TIMEOUT 1000;
IF @@rowcount = 0
begin
rollback
break;
end
set @sql = N'ALTER TABLE ' + quotename(@message) + N' WITH CHECK CONSTRAINT ALL'
exec (@sql)
if @@error <> 0
begin
rollback tran
break
end
COMMIT TRANSACTION
END
RETURN(0)
GO
设置队列和服务以发送和接收消息
CREATE QUEUE ConstraintQueueSend
CREATE SERVICE ConstraintServiceSend
CREATE QUEUE ConstraintQueueReceive
WITH STATUS = ON, ACTIVATION (PROCEDURE_NAME = p_enable_constraints
, MAX_QUEUE_READERS = 8
, EXECUTE AS SELF);
CREATE SERVICE [ConstraintServiceReceive] ON QUEUE ConstraintQueueReceive
现在创建一个为每个表提交消息的过程
CREATE PROC p_submit_enable_constraints_message @object sysname
AS
DECLARE @handle UNIQUEIDENTIFIER;
DECLARE @message sysname;
BEGIN TRANSACTION;
BEGIN DIALOG @handle FROM SERVICE [ConstraintServiceSend]
TO SERVICE [ConstraintServiceReceive]
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION @handle (@object);
COMMIT TRANSACTION;
END CONVERSATION @handle
GO
最后,我们可以调用该过程将其提交到队列中。
EXEC sp_msforeachtable 'EXEC p_submit_enable_constraints_message N''?'''
理想情况下,会捕获并发回alter table的结果。
答案 2 :(得分:0)
要检查的一件事是你是否在约束的两边都有索引(在正常操作期间,btw是一个好主意)。为了明确这一点,假设你有两个表(tbl_a和tbl_b)之间有一个FK约束(让我们说它是col_c)。你需要一个索引,其中tbl_a和tbl_b上的前导列是col_c,这样它就不必对没有这种索引的表进行表扫描。
此外,单独检查每个约束(而不是执行“检查约束全部”)将为您提供更好的粒度,如果您需要在中间停止。