我有许多功能可以将记录从一个表移动到另一个表(通常用于存档数据的形式)并且想知道是否存在"最佳实践"这样做,或者比我目前使用的更有效的方法。
目前,我正在运行类似:
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>
答案 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