我有一张有 340 万行的表。我想将整个数据复制到另一个表中。
我正在使用以下查询执行此任务:
select *
into new_items
from productDB.dbo.items
我需要知道完成这项任务的最佳方法。
我有一张有 340 万行的表。我想将整个数据复制到另一个表中。
我正在使用以下查询执行此任务:
select *
into new_items
from productDB.dbo.items
我需要知道完成这项任务的最佳方法。
我遇到了同样的问题,除了我有一个有 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 聚集,则此方法效果最佳。
如果您要复制到新表中,最快的方法可能就是您的问题,除非您的行非常大。
如果您的行非常大,您可能希望使用 SQL Server 中的批量插入函数。我认为您可以从 C# 调用它们。
或者,您可以先将该数据下载到文本文件中,然后批量复制 (bcp) 它。这具有允许您忽略键、索引等的额外好处。
还可以尝试 SQL Management Studio 附带的 Import/Export 实用程序;不确定它是否会像直接批量复制一样快,但它应该允许您跳过写成平面文件的中间步骤,直接从表到表复制,这可能比你的SELECT INTO
声明。
我一直在与我们的 DBA 合作,将具有 240M 行的审计表复制到另一个数据库。
使用简单的选择/插入创建了一个巨大的 tempdb 文件。
使用导入/导出向导有效,但在 10 分钟内复制了 8M 行
创建自定义 SSIS 包并调整设置在 10 分钟内复制了 30M 行
SSIS 包对我们的目的来说是最快和最有效的
伯爵
这是传输大表的另一种方法。我刚刚使用它在两台服务器之间传输了 1.05 亿行。也挺快的。
有关详细信息,请参阅https://www.mssqltips.com/sqlservertutorial/202/simple-way-to-export-data-from-sql-server/
如果是 1 次导入,SSMS 中的 Import/Export 实用程序可能会最简单、最快速地工作。SSIS 似乎也比直接插入更适合导入大型数据集。
BULK INSERT 或 BCP 也可用于导入大型记录集。
另一种选择是暂时删除要导入的表上的所有索引和约束,并在导入过程完成后将它们添加回来。在这些情况下,以前失败的直接 INSERT 可能会起作用。
如果您在直接从一个数据库到另一个数据库时处理超时或锁定/阻塞问题,您可以考虑从一个 db 进入 TEMPDB,然后从 TEMPDB 进入另一个数据库,因为它可以最大限度地减少锁定和阻塞进程对任何一边。TempDB 不会阻塞或锁定源,也不会阻止目标。
这些是一些可以尝试的选择。
——埃里克·艾萨克
简单的插入/选择 sp 的工作很好,直到行数超过 1 百万。我看到 tempdb 文件在尝试插入/选择 20 百万 + 行时爆炸。最简单的解决方案是 SSIS 将批处理行大小缓冲区设置为 5000,并将提交大小缓冲区设置为 1000。
我知道这已经很晚了,但是如果您遇到信号量超时,那么您可以使用 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 )
日志文件的大小会增长,因此需要应对。如果在插入现有表时禁用约束和索引,您将获得更好的性能。然后启用约束并在插入完成后为您插入的表重建索引。
如果您的重点是归档 (DW) 并且正在处理具有 100 多个分区表的 VLDB,并且您希望将这些资源密集型工作中的大部分隔离在非生产服务器 (OLTP) 上,这里有一个建议 (OLTP -> DW) 1) 使用备份/恢复将数据放到存档服务器上(所以现在,在存档或 DW 上,您将拥有 Stage 和 Target 数据库) 2)Stage 数据库:使用分区开关将数据移动到相应的 Stage 表
3)使用 SSIS 从为两侧的每个暂存表,暂存数据库到目标数据库 4)目标数据库:在目标数据库上使用分区开关将数据从阶段移动到基表 希望这会有所帮助。
从 productDB.dbo.items 中选择 * 进入 new_items
差不多就是这样。这是最有效的方法。