使用所有服务器资源在MS SQL 2005中针对大型表运行查询时出现问题

时间:2011-03-01 18:16:13

标签: sql sql-server sql-server-2005

我有一个MSSQL 2005数据库,其中包含孤立无用数据的GB。这些错误的数据导致数据库难以使用,需要4小时备份和7小时恢复。所有不良数据都在一个表格中。

我决定将数据导入另一个表并删除我认为不好的记录。所以我正在运行这样一个简单的SQL查询:

Insert databaseB.dbo.table (col1,col2) 
select col1,col2  from databaseA.dbo.table

在我不得不取消并重新启动sql服务之前,我最后一次尝试运行上述查询已经运行了12个小时而没有完成,因为在该服务器上使用任何数据库的任何应用程序都不会响应。

在此操作完成后,我将运行简单的删除“delete databaseA.dbo.table where condition = 1”,这是我上一次尝试锁定服务器时。

我正在尝试更新桌面上不需要任何锁定。

有关如何限制此查询以不影响此生产系统或其他生产系统的任何建议?我可以设置任何标志或选项,以使此运行更快或更顺畅吗? (比如更改恢复模型)如果需要它可以运行几天我只需要以某种方式限制使用的资源。如果我提供了足够的信息,请提前感谢您的任何建议。

我发现备份和恢复数据库到另一个位置。截断表,然后将好数据导回到相关表中。但由于完成第1步至少需要11个小时,而第2步的长度不详,我不喜欢这个选项。

4 个答案:

答案 0 :(得分:2)

在不影响其他操作的情况下执行此操作的最简单方法是使用游标传输信息并一次插入一行或手动循环遍历行。

有关游标,请参阅此处:http://msdn.microsoft.com/en-us/library/ms180169.aspx

循环:

  1. 选择10行
  2. 将它们导入新表格
  3. 删除那10行

    WHILE (SELECT COUNT(*) FROM YOUR_BAD_RECORDS) > 0
    BEGIN
        INSERT INTO TABLE...SELECT TOP 10 * FROM BAD_RECORDS
    END
    
  4. 直到作业完成为止。这将花费更长时间,但它不会锁定服务器资源并允许其他系统访问数据库。

答案 1 :(得分:1)

因为你提到这阻止了其他数据库活动,所以我觉得你遇到的问题是你在存档表中的插入是锁定正在被选中的记录并阻止其他用户。如果在生产时间内正在运行,您的声明也可能被其他活动阻止。

我建议使用增量流程来移动这些记录。您的标记表明您正在使用支持OUTPUT子句的SQL Server 2005,因此您可以删除旧记录并一次性将它们插入到归档表中。选择一次似乎合理的记录数,如果使用READPAST锁定提示,则不会阻止其他用户锁定的记录。只需根据需要多次运行批处理,也许作为计划任务。当然,请确保您的WHERE子句仅选择要存档的记录。

DELETE TOP (10000) FROM dbo.Valid_Date WITH (READPAST)
OUTPUT 
    DELETED.valid_date, DELETED.valid_date_KEY
    INTO dbo.Archive_Of_Valid_Date(valid_date, valid_date_KEY)
WHERE 
    valid_date < '19800101'

编辑扩展马修对我的回答的评论


使用COUNT(*)来确定是否有任何工作要做是不可用的,因此大多数时候你可以使用EXISTS(一旦发现任何匹配的记录就会短路)或使用声明后的@@ rowcount

WHILE (SELECT COUNT() FROM DatabaseA.dbo.table WHERE Condition=1) > 0 
BEGIN 
    DELETE TOP (100) FROM DatabaseA.dbo.table WITH (READPAST)
    OUTPUT 
        DELETED.x, DELETED.y
        INTO ArchiveDB.dbo.table(x, y)
    WHERE 
        condition = 1
END

尝试:

WHILE (1 = 1)
BEGIN 
    DELETE TOP (100) FROM DatabaseA.dbo.table WITH (READPAST)
    OUTPUT 
        DELETED.x, DELETED.y
        INTO ArchiveDB.dbo.table(x, y)
    WHERE 
        condition = 1

    IF(@@rowcount <= 0)
        break;
END

WHILE (EXISTS(SELECT * FROM DatabaseA.dbo.table WHERE Condition=1)) 
BEGIN 
    DELETE TOP (100) FROM DatabaseA.dbo.table WITH (READPAST)
    OUTPUT 
        DELETED.x, DELETED.y
        INTO ArchiveDB.dbo.table(x, y)
    WHERE 
        condition = 1
END

答案 2 :(得分:0)

从目标表中删除所有索引和外键。在清洁桌子后重新创建。

答案 3 :(得分:0)

而不是删除之后,只是不要插入将要删除的内容。

Insert databaseB.dbo.table (col1,col2) 
select col1,col2  from databaseA.dbo.table
where condition <> 1