2017-01-16 80 views
3

我在同一个数据库中有两个具有相同列结构的表:TableATableB如何在同一个数据库中将大量数据从一个表复制到另一个表中?

TableA没有任何索引,但TableB有一个非聚簇唯一索引。

TableA有290万行数据需要复制到TableB

,因为它们都具有相同的结构,我已经试过

INSERT INTO TableB 
    SELECT * 
    FROM TableA; 

它是为执行时间和产生的填充磁盘巨大的日志文件。结果磁盘空间不足,查询被终止。

我可以收缩日志文件。我怎样才能有效地将这些多行数据复制到另一个表中?

+1

检查了这可能会帮助你。 http://dba.stackexchange.com/questions/99367/insert-into-table-select-from-table-vs-bulk-insert –

+1

要复制2.9亿行,您将要将其分解为大块。不知道每行中有多少数据,但是当您在单个语句中执行此操作时,必须记录所有数据,以便在发生错误时可以回滚。将其分解为块或使用BulkInsert将缓解日志压力,因为它不会每个事务都需要太多数据。 –

+0

你有一个主键列,如果是的话是什么数据类型? –

回答

2

首先,在插入行之前禁用TableB上的索引。您可以使用T-SQL做到这一点:

ALTER INDEX IX_Index_Name ON dbo.TableB DISABLE; 

确保禁用所有约束(外键,检查约束,唯一索引)你的目标表。

加载完成后重新启用(并重建)它们。

现在,有一对夫妇的方法来解决这个问题:

  1. 你必须与数据丢失的轻微的机会OK:使用INSERT INTO ... SELECT ... FROM ...语法,你有,但切换你的数据库,以本体 - 先记录恢复模式(read before switching)。如果您已经处于Bulk-logged或Simple状态,将无济于事。
  2. 首先导出数据:您可以使用BCP实用程序导出/导入数据。它支持批量加载数据。阅读有关使用BCP实用程序here的更多信息。
  3. 花式,与第一导出数据:使用SQL 2012+你可以尝试将数据导出成二进制文件(使用BCP实用程序),并通过使用BULK INSERT声明加载它,设置ROWS_PER_BATCH选项。
  4. 老派“我不给一个该死的”方法:为了防止日志填满你需要执行 插入批次的行,而不是一次一切。如果您的数据库 正在完全恢复模式下运行,则需要保持日志备份 正在运行,甚至可能会尝试增加作业的频率。

    要批量加载行,您将需要一个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)指数 你 运行负载。

相关问题