如何将巨大的表数据复制到SQL Server中的另一个表中

时间:2011-03-14 08:05:22

标签: sql sql-server sql-server-2005 copying

我有一张340万行的表格。我想将这整个数据复制到另一个表中。

我正在使用以下查询执行此任务:

select * 
into new_items 
from productDB.dbo.items

我需要知道完成这项任务的最佳方法。

9 个答案:

答案 0 :(得分:67)

我遇到了同样的问题,除了我有一个20亿行的表,所以如果我这样做,日志文件会变得没有结束,即使将恢复模型设置为Bulk-Logging:

insert into newtable select * from oldtable

所以我操作数据块。这样,如果传输中断,您只需重新启动它。此外,您不需要与表一样大的日志文件。你似乎也得到更少的tempdb I / O,不知道为什么。

set identity_insert newtable on
DECLARE @StartID bigint, @LastID bigint, @EndID bigint
select @StartID = isNull(max(id),0) + 1
from newtable

select @LastID = max(ID)
from oldtable

while @StartID < @LastID
begin
    set @EndID = @StartID + 1000000

    insert into newtable (FIELDS,GO,HERE)
    select FIELDS,GO,HERE from oldtable (NOLOCK)
    where id BETWEEN @StartID AND @EndId

    set @StartID = @EndID + 1
end
set identity_insert newtable off
go

您可能需要更改ID的处理方式,如果您的表按ID进行群集,则效果最佳。

答案 1 :(得分:12)

如果要复制到 new 表中,最快的方法可能就是你的问题,除非你的行非常大。

如果您的行非常大,您可能希望在SQL Server中使用批量插入函数。我想你可以用C#打电话给他们。

或者您可以先将该数据下载到文本文件中,然后批量复制(bcp)它。这具有允许您忽略键,索引等的额外好处。

还可以尝试SQL Management Studio附带的导入/导出实用程序;不确定它是否会像直接批量复制一样快,但它应该允许你跳过作为平面文件写出的中间步骤,并且只是直接从表到表复制,这可能比你的SELECT INTO陈述。

答案 2 :(得分:10)

我一直在使用我们的DBA将具有240M行的审计表复制到另一个数据库。

使用简单的select / insert创建了一个巨大的tempdb文件。

使用导入/导出向导,但在10分钟内复制了8M行

创建自定义SSIS包并调整在10Min中复制30M行的设置

SSIS软件包对我们来说是最快和最有效的

厄尔

答案 3 :(得分:5)

这是传输大表的另一种方式。我使用它在两台服务器之间传输了1.05亿行。很快。

  1. 右键单击数据库,然后选择任务/导出数据
  2. 向导将指导您完成这些步骤,但您选择SQL Server客户端作为数据源,目标将允许您选择要传输的数据库和表。
  3. 有关详细信息,请参阅https://www.mssqltips.com/sqlservertutorial/202/simple-way-to-export-data-from-sql-server/

答案 4 :(得分:2)

If it's a 1 time import, the Import/Export utility in SSMS will probably work the easiest and fastest. SSIS also seems to work better for importing large data sets than a straight INSERT.

BULK INSERT or BCP can also be used to import large record sets.

Another option would be to temporarily remove all indexes and constraints on the table you're importing into and add them back once the import process completes. A straight INSERT that previously failed might work in those cases.

If you're dealing with timeouts or locking/blocking issues when going directly from one database to another, you might consider going from one db into TEMPDB and then going from TEMPDB into the other database as it minimizes the effects of locking and blocking processes on either side. TempDB won't block or lock the source and it won't hold up the destination.

Those are a few options to try.

-Eric Isaacs

答案 5 :(得分:1)

简单插入/选择sp的效果很好,直到行数超过100万。我已经看到tempdb文件爆炸,试图插入/选择20 mil +行。最简单的解决方案是SSIS将批处理行大小缓冲区设置为5000,并将提交大小缓冲区设置为1000。

答案 6 :(得分:0)

如果您的重点是存档(DW)并正在处理具有100多个分区表的VLDB,并且您想在非生产服务器(OLTP)上隔离大多数这些资源密集型工作,则建议(OLTP-> DW) 1)使用备份/还原将数据获取到存档服务器上(因此,现在,在存档或DW上,您将拥有Stage和Target数据库) 2)阶段数据库:使用分区开关将数据移至相应的阶段表
3)使用SSIS将数据从暂存数据库传输到双方的每个暂存表的目标数据库 4)目标数据库:使用目标数据库上的分区开关将数据从阶段移动到基表 希望这会有所帮助。

答案 7 :(得分:0)

我知道这已经晚了,但是如果您遇到信号量超时,那么您可以使用 row_number 使用类似的东西为您的插入设置增量

INSERT INTO DestinationTable (column1, column2, etc) 
 FROM ( 
SELECT ROW_NUMBER() OVER (ORDER BY ID) AS RN , column1, column2, etc
FROM SourceTable ) AS A
WHERE A.RN >= 1 AND A.RN <= 10000 )

日志文件的大小会增加,因此需要解决这个问题。如果在插入现有表时禁用约束和索引,则会获得更好的性能。然后启用约束并在插入完成后为您插入的表重建索引。

答案 8 :(得分:-8)

  

从productDB.dbo.items中选择* into new_items

这就是它。这是最有效的方法。