有效传输大量(8400万行)数据


11

我大约有8400万行。所有这些都需要转移到同一服务器上的单独数据库中,然后我删除以从源数据库中删除大约6000万行。

8400万行都在同一表中。仅该表就占整个数据库的90%。

因此...来源:8400万行-> 2400万行目标:0行-> 8400万行

源运行完全恢复模式,目标将运行简单。

我想知道最有效的方法是什么?

计划A:

1)插入目标SELECT * FROM源

2)截断源

3)插入源SELECT * FROM目标WHERE keep_condition = 1

方案B:

1)将源数据库的备份还原为目标数据库

2)删除除目标数据库所需表之外的所有表

3)截断源

4)插入源SELECT * FROM目标WHERE keep_condition = 1

计划C:

1)插入目标SELECT * FROM源

2)删除源WHERE keep_condition = 0

或者是其他东西?

谢谢


为什么不使用“导入和导出数据”向导?它是SQL Server安装随附的工具。
Hani El Mouallem

是否可以将2千4百万行复制到新表中,然后根据需要简单地重命名两行,这样就不会不必要地移动8400万行?
LowlyDBA 2014年

这是一次性的还是正在进行的过程?我问是因为考虑到处理8000万行所需要的时间,SOURCE生产行中的数据可能会发生变化,这些行现在应该位于DESTINATION中。
Michael Green

这看起来像一个XY问题:您需要在一个DB中结束所有84MM行,而在另一个DB中结束所有24MM行。哪些业务需求要求移动84MM并删除60M,而不仅仅是移动24MM?链接:meta.stackexchange.com/questions/66377/what-is-the-xy-problem
Pieter Geerkens

我有一个非常类似的问题,显然不是XY。在有关记录保留的法律激增之前,我们保留了所有数据。现在,我们必须删除比保留法律要求的日期早的行。这意味着需要归档和删除超过20年的数据,因为在大多数情况下,合法保留时间为7年。我不认为我一个人会相信Microsoft不会为存储过程不提供“批量复制”功能。应用程序在数据库内“移动”数据的速度不应比数据库本身快。明年必须将另一年存档。
bielawski,

Answers:



3

“有效”可能适用于日志文件使用情况,I / O性能,CPU时间或执行时间。

我将尝试实现最少日志记录的操作,从日志记录的角度来看,这将是相当有效的。这样可以为您节省一些执行时间,这是一个额外的好处。如果您有tempdb空间,则可能需要执行以下操作。

CREATE TABLE #temp;
ALTER source -> BULK_LOGGED recovery model

BEGIN TRANSACTION;

    INSERT INTO dest SELECT FROM source;
    INSERT INTO #temp SELECT FROM source WHERE keep_condition=1;
    TRUNCATE TABLE source;
    INSERT INTO source SELECT FROM #temp;

COMMIT TRANSACTION;

ALTER source -> FULL recovery model
DROP TABLE #temp;

为了使日志记录最少,必须满足许多条件,包括当前没有正在运行的备份,数据库设置为BULK_LOGGED恢复模式,并且取决于您的索引,目标表可能必须为空。从SQL Server 2005到2008,某些这种行为也发生了变化(改进)。

再说一次,在不了解表和数据细节的情况下,其他任何选项的性能都可能更好。尝试使用

SET STATISTICS IO ON;
SET STATISTICS TIME ON;

..看看哪个效果最好。

编辑:执行批量记录的操作时,如果需要时间点还原功能并且怀疑其他活动可能正在数据库中进行,请确保在操作之前和之后进行备份(完整或事务日志)。在您的ETL作业运行的同时。

不久前,我写了一篇关于最小记录操作的博客文章,其中有指向其他文章和文档的链接。


+1表示建议OP测试以查看效果更好。当然,这可能是有点难以得到,除非(S)实数,他在开发一个重复系统,等等
最大弗农

只是一个问题,如果您尝试在数据库处于批量记录模式下进行时间点还原,将会发生什么?我以为任何不符合“批量”条件的交易都是可以恢复的。
elty123

1
@ elty123在大容量日志恢复中,您只能还原到最后一次日志备份的结尾。没有任何时间可以像完全恢复那样进行时间恢复。通常,您切换到批量日志恢复,运行一些ETL过程,切换回完整状态,然后进行日志备份。
RubberChickenLeader 2014年

@WindRaven这是不正确的-请在下面查看我的答案。
wBob

1
@wBob和@WindRaven,我更新了答案以反映使用BULK_LOGGED模式之前和之后进行备份的需要。谢谢!
Daniel Hutmacher 2014年

1

为什么不使用BCP?

  1. 备份sourcedb
  2. 将sourcedb更改为批量记录
  3. 打开命令提示符

  4. bcp server.sourcedb.table out Filename.flt -T -c

  5. bcp "SELECT * FROM sourcedb.table WHERE keep_condition = 1" queryout Filename2.flt -T -c

  6. bcp Server.destinationdb.table in Filename.flt -T -c -b1000

  7. 检查数据

  8. 从SSMS截断sourcedb表
  9. bcp server.sourcedb.table in Filename2.flt -T -c -b1000
  10. 将sourcedb重新更改为完整

2
因为它们在同一台服务器上。写入文件系统将很昂贵。最好创建数据库并对数据库进行大小调整,以期利用即时文件初始化的优势。对于不同服务器上的数据库,这将是一个合理的选择,尽管如果可能的话,SSIS将是我的首选。注意:选项-n(本机)对于将数据从SQL Server迁移到SQL Server而言更为紧凑和安全。选项-b对于bcp输出无效。
wBob

0

不要以为您建议不要在之前和之后都没有完整的数据库备份或t-log备份的情况下更改恢复模型。BULK_LOGGED恢复模型的功能之一是您将无法对包含批量记录操作的t-log执行时间点恢复。经典方案:每晚完整备份,每小时t-log备份。您将恢复模型更改为批量记录并开始操作。发生错误,事务回滚(或者您没有使用过)。但是,您不确定数据库中还有什么其他情况,因此您想还原到已知的好点。

什么时候可以恢复到?最后每小时T-日志备份,它包含大容量日志操作,可能会丢失数据的n分钟。在更改恢复模型之前,完整备份或t-log备份将创建一个后备点。选择哪一个取决于您的RTO。


0

从表中删除分区是从表中删除大块数据的一种非常快速且节省资源的方法。如果以支持源/目标拆分的方式对表进行分区,答案将是还原副本,从目标删除冗余表和冗余分区,以及从源删除互补分区。

但是,启用分区的成本可能会使操作总体上更加昂贵。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.