从巨大的表中删除数据

时间:2012-05-16 18:02:11

标签: sql-server sql-server-2008 tsql sql-server-2005

我有几个表,所有表都有大约500万行,每个表中都有Active列。我想从Active = 0的所有表中删除数据。使用delete需要花费大量时间,而且由于它具有外键约束和标识字段,因此我无法截断表。

有一种有效的方法吗?

6 个答案:

答案 0 :(得分:1)

我仍然是一名JR程序员,但如果你删除的东西非常大,只有一个字段(Active = 0),但这需要很长时间。你有两种选择。

1)运行该查询,并耐心等待。

2)找到另一种方法将查询分成几个较小的查询。例如,active = 0和用A-G开头的用户名,然后另一个用户名来自H-P,依此类推。 (伪示例,但你明白了我的想法?)

答案 1 :(得分:0)

答案 2 :(得分:0)

要记住的另一件事是复制。如果表很大,并且您必须删除大量记录,则可能需要在发生如此多的删除后放置waitfor delay,这样就不会使复制命令泛滥。

答案 3 :(得分:0)

declare @batchsize int 10000;

while(1=1)
begin
   delete top (@batchsize) 
   from your_table 
   where isActive = 0;

   if (@@rowcount = 0)
   begin
      break
   end
end

如果找到isActive = 0的行是“昂贵的”(即非索引选择),您可能需要先将这些行的主键选择到临时表中,然后根据表格从表中删除与临时表的连接。

答案 4 :(得分:0)

试试这个。

这个想法是复制表,重新创建表,并复制活动数据

  1. SSMS>右键单击该表并选择脚本表作为 - 创建到 - 新窗口(不执行)
  2. 将现有表重命名为其他名称。
  3. 在第1步上运行脚本
  4. 从重命名表运行复制脚本到新创建的表

    从RenamedTable插入newtable select *,其中active = 1

  5. 删除RenamedTable

  6. 让我知道它是怎么回事。

答案 5 :(得分:-1)

这是我过去用来批量删除行的模板,你可以尝试一下:

-- Pick the boundaries of the data you want to delete based on
-- the Primary Key of your table
DECLARE
    @StartID INT, -- Pick the appropriate datatype of your PK
    @EndID INT, -- Pick the appropriate datatype of your PK
    @BatchSize INT, -- Number of rows to delete in batch
    @Count INT -- Temporary counter of rows deleted

SELECT TOP 1
    @StartID = PrimaryKeyID
FROM
    dbo.Table WITH (NOLOCK)
ORDER BY
    PrimaryKeyID ASC

SELECT TOP 1
    @EndID = PrimaryKeyID
FROM
    dbo.Table WITH (NOLOCK)
ORDER BY
    PrimaryKeyID DESC

SELECT
    @BatchSize = 1000,
    @Count = 1

-- You can skip this table if you like
-- The idea is to reduce the number of rows processed
-- in the batch below
CREATE TABLE #Temp
(
    [ID] INT
)

WHILE @Count > 0
BEGIN
    TRUNCATE TABLE #Temp

    DELETE TOP (@BatchSize)
    FROM
        dbo.Table WITH (ROWLOCK)
    OUTPUT
        DELETED.PrimaryKeyID
    INTO #Temp
    (
        [ID]
    )
    WHERE
        PrimaryKeyID >= @StartID
    AND PrimaryKeyID <= @EndID
    AND Active = 0

    SET @Count = @@ROWCOUNT

    IF @Count = 0
    BEGIN
        BREAK
    END

    -- Move the @StartID
    SELECT TOP 1
        @StartID = [ID]
    FROM
        #Temp
    ORDER BY
        [ID] DESC

    WAITFOR DELAY '00:01' -- delay for 1 second to allow any other queries running to process
END