如何在同一个数据库中将大量数据从一个表复制到另一个表中?
问题描述:
我在同一个数据库中有两个具有相同列结构的表:TableA
和TableB
。如何在同一个数据库中将大量数据从一个表复制到另一个表中?
TableA
没有任何索引,但TableB
有一个非聚簇唯一索引。
TableA
有290万行数据需要复制到TableB
。
,因为它们都具有相同的结构,我已经试过
INSERT INTO TableB
SELECT *
FROM TableA;
它是为执行时间和产生的填充磁盘巨大的日志文件。结果磁盘空间不足,查询被终止。
我可以收缩日志文件。我怎样才能有效地将这些多行数据复制到另一个表中?
答
首先,在插入行之前禁用TableB
上的索引。您可以使用T-SQL做到这一点:
ALTER INDEX IX_Index_Name ON dbo.TableB DISABLE;
确保禁用所有约束(外键,检查约束,唯一索引)你的目标表。
加载完成后重新启用(并重建)它们。
现在,有一对夫妇的方法来解决这个问题:
-
你必须与数据丢失的轻微的机会OK:使用
INSERT INTO ... SELECT ... FROM ...
语法,你有,但切换你的数据库,以本体 - 先记录恢复模式(read before switching)。如果您已经处于Bulk-logged或Simple状态,将无济于事。 - 首先导出数据:您可以使用BCP实用程序导出/导入数据。它支持批量加载数据。阅读有关使用BCP实用程序here的更多信息。
-
花式,与第一导出数据:使用SQL 2012+你可以尝试将数据导出成二进制文件(使用BCP实用程序),并通过使用BULK INSERT声明加载它,设置
ROWS_PER_BATCH
选项。 -
老派“我不给一个该死的”方法:为了防止日志填满你需要执行 插入批次的行,而不是一次一切。如果您的数据库 正在完全恢复模式下运行,则需要保持日志备份 正在运行,甚至可能会尝试增加作业的频率。
要批量加载行,您将需要一个
WHILE
(不 一天到一天的东西使用它们,只是批量负荷),有点像 以下会,如果你有在标识工作dbo.TableA
表:DECLARE @RowsToLoad BIGINT; DECLARE @RowsPerBatch INT = 5000; DECLARE @LeftBoundary BIGINT = 0; DECLARE @RightBoundary BIGINT = @RowsPerBatch; SELECT @RowsToLoad = MAX(IdentifierColumn) dbo.FROM TableA WHILE @LeftBoundary < @RowsToLoad BEGIN INSERT INTO TableB (Column1, Column2) SELECT tA.Column1, tB.Column2 FROM dbo.TableA as tA WHERE tA.IdentifierColumn > @LeftBoundary AND tA.IdentifierColumn <= @RightBoundary SET @LeftBoundary = @LeftBoundary + @RowsPerBatch; SET @RightBoundary = @RightBoundary + @RowsPerBatch; END
对于这个工作有效地你真的要考虑只是时间上创建一个
dbo.TableA (IdentifierColumn)
指数 你 运行负载。
检查了这可能会帮助你。 http://dba.stackexchange.com/questions/99367/insert-into-table-select-from-table-vs-bulk-insert –
要复制2.9亿行,您将要将其分解为大块。不知道每行中有多少数据,但是当您在单个语句中执行此操作时,必须记录所有数据,以便在发生错误时可以回滚。将其分解为块或使用BulkInsert将缓解日志压力,因为它不会每个事务都需要太多数据。 –
你有一个主键列,如果是的话是什么数据类型? –