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

Posted

技术标签:

【中文标题】SQL Server如何将一个巨大的表数据复制到另一个表中【英文标题】:How to copy a huge table data into another table in SQL Server 【发布时间】:2011-07-14 20:15:48 【问题描述】:

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

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

select * 
into new_items 
from productDB.dbo.items

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

【问题讨论】:

什么是 34 lac 记录?百万?不休……理所当然,不小,但不休。 能否暂时将恢复模式设置为简单? “Not Hugh...granted” - 经典的@TomTom!! 如何编辑别人的评论 【参考方案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 )

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

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

【讨论】:

【参考方案4】:

我遇到了同样的问题,除了我有一个包含 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 进行聚类,这会最有效。

【讨论】:

类似的方法是使用DECLARE @offset int SELECT COUNT(*) = @offset FROM newtable...ORDER BY [key(s)] OFFSET @offset ROWS FETCH NEXT @step ROWS ONLY,如果pk 或聚集索引是多列的,则更容易 ? 应该说DECLARE @offset int SELECT @offset = COUNT(*) FROM newtable @offset 方法可能会随着偏移量变大而变慢,我不确定 SQL Server 如何优化偏移选择。 我假设它使用类似于优化WHERE 的索引来优化OFFSET,但我不是DBA¯_(ツ)_/¯ 自 2013 年以来我没有使用过 SQL Server...【参考方案5】:

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

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

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

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

事实证明,SSIS 包对我们来说是最快和最有效的

伯爵

【讨论】:

你还记得“调整设置”吗?【参考方案6】:

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

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

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

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

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

-埃里克·艾萨克

【讨论】:

【参考方案7】:

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

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

欲了解更多信息,请参阅https://www.mssqltips.com/sqlservertutorial/202/simple-way-to-export-data-from-sql-server/

【讨论】:

此技术代表您构建和运行 SSIS 包。您确实可以选择保存但不执行它创建的包。这使您可以在运行前打开它并调整每批次的行数等内容,以优化您的表特征和系统资源,同时省去从头开始编写包的麻烦。【参考方案8】:

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

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

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

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

【讨论】:

我知道这有点晚了,但只是想分享一下,在我的情况下(有 70M 行非常大的行),导入/导出实用程序往往会显示 Deferred prepare could not be completed. Query timeout expired (Microsoft SQL Server Native Client 10.0) 错误。跨度> 【参考方案9】:

select * into new_items from productDB.dbo.items

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

【讨论】:

在输入字符方面可能是最有效的。

以上是关于SQL Server如何将一个巨大的表数据复制到另一个表中的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 中复制数据的存储过程

如何将一个数据库中的一个表复制到另一个数据库中的表中

如何将 sql server 中所有数据的单个视图从一个数据库复制到另一个数据库?

SQL语句如何把一个表的数据复制到另一个表里面

在 SQL Server 中将表从一个数据库复制到另一个数据库

怎么复制sqlserver数据库里所有的表到另一个数据库中