如何在不丢失数据的情况下删除SQL Server中的大量数据?

时间:2019-04-25 07:32:43

标签: sql sql-server performance sql-server-2012 sql-delete

我每天都在处理数百万个数据的删除。

基本上我有4张桌子。

Table_A
Table_B
Table_C
Table_D

我正在尝试删除所有表中超过10天的数据。

可能我将在每个表中删除大约一百万。我创建了一个存储过程来执行这些操作。

我要删除数据的步骤是

步骤1:将最近几天(我必须保留的数据)移到临时表中

select * into Table_A_Temp
from Table_A
where <<where clause last 10 days to till date>>

第2步:将主表重命名为旧表(包含全天数据的表)

exec sp_rename 'Table_A', 'Table_A_Old'

第3步:将临时表重命名为主表(该表中包含前几天到截止日期之间的数据)

exec sp_rename 'Table_A_temp', 'Table_A'

步骤4:在复制过程中是否插入任何新数据的情况下,查询具有时间范围的临时表

Insert into Table_A
select * from Table_A_old

第5步:删除旧表

DROP TABLE Table_A_old

步骤6:在主表(意味着重命名表)中创建键和约束

code to create primary keys and constraints

问题:

如果我在存储过程运行时不断将数据插入表中,那么我将丢失数据几秒钟。

情况1:重命名表格

当我将main重命名为old并将temp表重命名为main

我收到无效对象错误(该表存在错误)

案例2:我的两个表具有外键关系

如果我在创建约束和键之前插入数据,则会遇到相关错误。

如何正确处理和删除数据而不丢失数据。

请告知最佳做法。

3 个答案:

答案 0 :(得分:1)

为避免丢失数据,我只删除与创建/重命名表相反的记录。 SQL Server将为您处理插入和删除操作,以防止数据丢失。您可以通过几种方法来做到这一点,以下是一个建议。

第1步:获取要删除的行的ID /标识符,并将其存储在临时表中。

SELECT Id 
INTO #TEMP_Table_A_RowsToDelete
FROM Table_A
WHERE <<your_date_column <= 10 days ago>>

然后,您将得到一个临时表#TEMP_Table_A_RowsToDelete,其中包含要删除的行的Id值。

第2步(可选):使用此表删除引用表中的所有相关数据(如果存在)。

DELETE t1
FROM ForeignKeyTable t1
INNER JOIN #TEMP_Table_A_RowsToDelete t2
  ON t1.[ForeignKeyColumn] = t2.Id

这将删除链接到主表上主键的表中的所有相关数据。您将对所有链接表重复此操作,以确保外键约束不会阻止您删除父表中的行。

第3步:从主表中删除行。

DELETE t1
FROM Table_A t1
INNER JOIN #TEMP_Table_A_RowsToDelete t2
  ON t1.[Id] = t2.Id

这将根据在步骤1中添加到临时表中的内容删除10天以上的行。如果您在步骤2中删除了所有相关数据,则不会造成问题。

您将需要对列表中的每个表重复上述步骤。

答案 1 :(得分:1)

大概这是一个持续的需求。

您应该做的是对表进行分区。存在的地方是了解documentation中的分区。

可能最简单的方法如下:

  • 将每个表复制到新位置。
  • 重新定义每个表并添加分区功能。
  • 将数据重新加载到表中。

对于第三步,只需加载所需的最新数据即可。

然后,将来您可以每天简单地删除最旧的分区。您可以设置一个SQL Server代理作业来执行此操作,系统将自动运行。

答案 2 :(得分:0)

我正在考虑在table_A上进行插入/更新和删除触发器的选项。此触发器将数据复制到#TEMP_Table。您可以在10天后重命名两个表

第1步创建触发器,将数据复制到新表“ #TEMP_Table”

 CREATE TRIGGER trig_table_a_copy
 ON [Table_A]
 AFTER UPDATE
 AS BEGIN
     (excess code)       
 END

 AFTER INSERT
 AS BEGIN
  (excess code)
 END

 AFTER DELETE
 AS BEGIN
    (excess code)
 END
  GO

步骤2等待10天。检查两个表是否具有相同的数据

步骤3重命名表格

exec sp_rename 'Table_A', 'Table_A_Old'
exec sp_rename '#TEMP_Table', 'Table_A'

第4步删除旧表。

DROP TABLE Table_A_old