将表行从一个表移动到另一个表的最有效方法

时间:2012-02-08 01:34:15

标签: .net sql-server sql-server-2008 denormalization sql-job

我创建了一个非规范化表,需要每小时插入/更新一次。从数据的角度来看,这个过程非常复杂,所以我正在寻找一种推荐的方法来更新表而不会中断用户。

我正在考虑让我的流程插入/更新一个单独的表,一旦完成,需要一种方法将这些更改推送到我的实时生产表。

任何帮助都会很棒!

2 个答案:

答案 0 :(得分:4)

另一种解决方案是使用多个模式并播放switch-a-roo。我只喜欢这种方法,因为我曾经在工作中做过这个技巧,而关于重命名对象(无法抑制)的警告信息填满了我的历史记录。基本上你需要两个额外的模式(一个临时保存表的副本,一个保存缓存的副本)。

CREATE SCHEMA cache AUTHORIZATION dbo;
CREATE SCHEMA hold  AUTHORIZATION dbo;

现在,在缓存模式中创建表的模仿:

SELECT * INTO cache.table FROM dbo.table WHERE 1 = 0;
-- then create any indexes etc.

现在是时候刷新数据了:

-- step 1:
TRUNCATE TABLE cache.table;
-- (if you need to maintain FKs you may need to delete)
INSERT INTO cache.table SELECT ...

-- step 2:
-- this transaction will be almost instantaneous, 
-- since it is a metadata operation only: 

BEGIN TRANSACTION;
  ALTER SCHEMA hold  TRANSFER dbo.table;
  ALTER SCHEMA dbo   TRANSFER cache.table;
  ALTER SCHEMA cache TRANSFER hold.table;
COMMIT TRANSACTION;

理论上,您可以将最后一次转移移出交易,因为用户可以在第二次转移后开始查询dbo.table的新副本,但就像我说的那样,这几乎是瞬间的如果你发现并发性有任何不同,我会感到惊讶。

您也可以选择在此处再次截断cache.table,但我始终将其填充,以便我可以比较数据更改或在出现问题时进行故障排除。根据步骤1所用的时间长短,反向执行传输可能比从头重新填充更快。

与重命名一样,你可以从这个过程中得到不可思议的东西,比如统计数据随着实际表格移动而丢失,他们不会坚持使用名称。就像重命名一样,你会想要测试它,你可能想要玩隔离级别,例如RCSI用于访问报告表。

答案 1 :(得分:2)

一种解决方案是使用您提到的临时表来执行此操作,然后将其名称更改为生产表名称(但首先,将生产表重命名为其他名称)。之后,您可以放弃以前的生产表。当然,你应该在交易中完成所有这些工作。

所以,它将是:

-- Fill tmpTable
--

-- Do renaming
begin tran t1;
execute sp_rename 'productionTable', 'productionTableBackup';
execute sp_rename 'tmpTable', 'productionTable';
commit tran t1;