SQL MOVE记录到另一个表

时间:2015-04-20 14:40:20

标签: sql sql-server-2008

我有许多功能可以将记录从一个表移动到另一个表(通常用于存档数据的形式)并且想知道是否存在"最佳实践"这样做,或者比我目前使用的更有效的方法。

目前,我正在运行类似:

INSERT INTO archive_table
SELECT [ROWID], [COL1], [COL2]
FROM live_table
WHERE <criteria>

DELETE FROM live_table
WHERE [ROWID] IN
(
   SELECT [ROWID] FROM archive_table
)

这也在SQL性能软件上发出警告,该查询可能导致索引抑制和性能下降;由于正在执行SCAN,而不是SEEK。

值得补充的是,archive_table是live_table的精确副本,但我们已删除了[ROWID]列中的标识和主键,并且该表未在&#39; live&#中使用39;环境,除了插入旧数据,如上所述。

[编辑]

似乎Alex的答案为此提供了一个非常简单的解决方案;关于使用触发器的注释在此实例中没有解决问题,因为事件发生在几天之后,并且标准取决于该期间的事件。

DELETE 
FROM live_table 
OUTPUT DELETED.* INTO archive_table
WHERE <criteria>

3 个答案:

答案 0 :(得分:1)

如果您必须将大量记录从一个表移动到另一个表,我建议您检查是否可以对“活动表”进行分区。每次,您将数据从一个(或多个)分区复制到“实现表”并删除这些分区。它比从“在线”表中删除记录要快得多。

答案 1 :(得分:0)

  

值得补充的是,archive_table是live_table的精确副本,但我们已删除了[ROWID]列中的标识和主键,并且该表未在&#39; live&#中使用39;环境,除了插入旧数据,如上所述。

我无法判断您是否从archive_table中删除主键是因为您希望ROWID在live_table中重复使用。

如果我正确理解数据的上下文并且您希望在数据完成后几天存档,则可以通过减少/消除不存在的行的比较来提高查询的性能。 live_table。基本上,一旦ROWID从live_table迁移到archive_table,就没有理由再次查找它。

注意:这假设ROWID不会在live_table中重复使用,而且总是在增加数字。

INSERT INTO archive_table
SELECT [ROWID], [COL1], [COL2]
FROM live_table
WHERE <criteria>

DELETE FROM live_table
WHERE [ROWID] IN
(
   SELECT [ROWID] FROM archive_table WHERE [ROWID] >= (SELECT MIN(ROWID) FROM live_table)
)

如果重复使用ROWID。如果数据集中的日期时间字段与记录生存或存档时接近,则可以将其用作ROWID的替代字段。这意味着您只需要查找最近存档的行,以便从live_table中删除,而不是整个集合。另外,在archive_table上设置[somedate]聚簇索引可以提高性能,因为数据将物理地排序到只查看表尾的位置。

INSERT INTO archive_table
SELECT [ROWID], [COL1], [COL2]
FROM live_table
WHERE <criteria>

DELETE FROM live_table
WHERE [ROWID] IN
(
   SELECT [ROWID] FROM archive_table WHERE [somedate] >= DATEADD(dy,-30,GETDATE())
)

答案 2 :(得分:0)

您的代码段不包含必须首先考虑的命名事务。第二个设计一个表变量,临时表或硬表用于分段。设计的表应包含与源表中的标识列数据类型相同的列,并且该列应编入索引。第三,设计TSQL以填充登台表,根据源和登台之间的连接将行从源表复制到目标表,然后根据将数据移动到目标表的同一连接从源表中删除行。以下是工作样本

--test setup below
DECLARE @live_table table (rowid int identity (1,1) primary key clustered, col1 varchar(1), col2 varchar(2))
DECLARE @archive_table table (rowid int, col1 varchar(1), col2 varchar(2))

Insert @live_table (col1,   col2)
Values 
('a','a'),
('a','a'),
('a','a'),
('a','a'),
('b','b')
--test setup above

BEGIN Transaction MoveData

    DECLARE @Staging table (ROWID int primary Key)

    Insert @Staging 
    SELECT lt.rowid
    FROM @live_table as lt
    WHERE lt.col1 = 'a'

    INSERT INTO @archive_table
    select lt.rowid, lt.col1, lt.col2
    FROM @live_table as lt
    inner join @Staging as s on lt.rowid = s.ROWID

    DELETE @live_table
    FROM @live_table as lt
    inner join @Staging as s on lt.rowid  = s.ROWID

COMMIT Transaction MoveData

select * from @live_table
select * from @archive_table
select * from @Staging