42

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

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

select * 
into new_items 
from productDB.dbo.items

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

4

9 回答 9

90

我遇到了同样的问题,除了我有一个有 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 聚集,则此方法效果最佳。

于 2011-09-08T20:59:10.023 回答
18

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

如果您的行非常大,您可能希望使用 SQL Server 中的批量插入函数。我认为您可以从 C# 调用它们。

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

还可以尝试 SQL Management Studio 附带的 Import/Export 实用程序;不确定它是否会像直接批量复制一样快,但它应该允许您跳过写成平面文件的中间步骤,直接从表到表复制,这可能比你的SELECT INTO声明。

于 2011-03-14T08:20:05.930 回答
12

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

使用简单的选择/插入创建了一个巨大的 tempdb 文件。

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

创建自定义 SSIS 包并调整设置在 10 分钟内复制了 30M 行

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

伯爵

于 2015-12-22T16:51:01.353 回答
8

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

  1. 右键单击数据库并选择Tasks/Export Data
  2. 向导将引导您完成这些步骤,但您选择 SQL Server 客户端作为数据源和目标将允许您选择要传输的数据库和表。

有关详细信息,请参阅https://www.mssqltips.com/sqlservertutorial/202/simple-way-to-export-data-from-sql-server/

于 2015-09-17T11:47:39.203 回答
4

如果是 1 次导入,SSMS 中的 Import/Export 实用程序可能会最简单、最快速地工作。SSIS 似乎也比直接插入更适合导入大型数据集。

BULK INSERT 或 BCP 也可用于导入大型记录集。

另一种选择是暂时删除要导入的表上的所有索引和约束,并在导入过程完成后将它们添加回来。在这些情况下,以前失败的直接 INSERT 可能会起作用。

如果您在直接从一个数据库到另一个数据库时处理超时或锁定/阻塞问题,您可以考虑从一个 db 进入 TEMPDB,然后从 TEMPDB 进入另一个数据库,因为它可以最大限度地减少锁定和阻塞进程对任何一边。TempDB 不会阻塞或锁定源,也不会阻止目标。

这些是一些可以尝试的选择。

——埃里克·艾萨克

于 2015-10-30T22:53:46.600 回答
2

简单的插入/选择 sp 的工作很好,直到行数超过 1 百万。我看到 tempdb 文件在尝试插入/选择 20 百万 + 行时爆炸。最简单的解决方案是 SSIS 将批处理行大小缓冲区设置为 5000,并将提交大小缓冲区设置为 1000。

于 2018-08-08T15:12:45.403 回答
1

我知道这已经很晚了,但是如果您遇到信号量超时,那么您可以使用 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 )

日志文件的大小会增长,因此需要应对。如果在插入现有表时禁用约束和索引,您将获得更好的性能。然后启用约束并在插入完成后为您插入的表重建索引。

于 2021-04-16T16:35:42.697 回答
0

如果您的重点是归档 (DW) 并且正在处理具有 100 多个分区表的 VLDB,并且您希望将这些资源密集型工作中的大部分隔离在非生产服务器 (OLTP) 上,这里有一个建议 (OLTP -> DW) 1) 使用备份/恢复将数据放到存档服务器上(所以现在,在存档或 DW 上,您将拥有 Stage 和 Target 数据库) 2)Stage 数据库:使用分区开关将数据移动到相应的 Stage 表
3)使用 SSIS 从为两侧的每个暂存表,暂存数据库到目标数据库 4)目标数据库:在目标数据库上使用分区开关将数据从阶段移动到基表 希望这会有所帮助。

于 2019-05-02T14:30:06.907 回答
-12

从 productDB.dbo.items 中选择 * 进入 new_items

差不多就是这样。这是最有效的方法。

于 2011-03-14T08:08:33.607 回答