在 SQL Server 2005 中从小表批量复制到大表

Posted

技术标签:

【中文标题】在 SQL Server 2005 中从小表批量复制到大表【英文标题】:Bulk Copy from small table to larger one in SQL Server 2005 【发布时间】:2011-08-31 02:31:14 【问题描述】:

我是 SQL Server 的新手,遇到以下困境:

我有两个结构相同的表。称它为runningTblfinalTbl

runningTbl 每 15 分钟包含大约 600 000 到 100 万行。

runningTbl 中进行一些数据清理后,我想将所有记录移动到finalTblfinalTbl 目前大约有 3800 万行。

以上过程需要每15-20分钟重复一次。

问题在于,将数据从 runningTbl 移动到 finalTbl 有时需要超过 20 分钟。

最初,当表格很小时,复制需要 10 秒到 2 分钟。

现在需要的时间太长了。

任何人都可以帮助解决这个问题?要遵循的 SQL 查询..

谢谢

【问题讨论】:

到目前为止,我已经尝试了两种不同的查询... Q1: INSERT INTO [mydb].[dbo].[processed_logs] ([UnixTime] ,[ElapsedTime] ,[ClientIP] ,[Trans ] ,[ResponseSize] ,[Request1] ,[RequestAddress] ,[FullUserName] ) SELECT [UnixTime] ,[ElapsedTime] ,[ClientIP] ,[Trans] ,[ResponseSize] ,[ofRequest1] ,[RequestAddress] ,[FullUserName] FROM [mydb].[dbo].[unprocessed_logs] 到目前为止您尝试过哪些查询?您是否尝试过使用 SELECT INTO? 表上有索引吗?可以贴一下查询的执行计划吗? DECLARE @FileName varchar(50), @bcpCommand varchar(2000) SET @FileName = 'E:\export\templog.swork' --export SET @bcpCommand = 'bcp "SELECT * FROM mydb ..unprocessed_logs" queryout "' SET @bcpCommand = @bcpCommand + @FileName + '" -U 用户 -P 密码 -c' EXEC master..xp_cmdshell @bcpCommand --import SET @bcpCommand = 'bcp "mydb..processed_logs"在 "' SET @bcpCommand = @bcpCommand + @FileName + '" -U 用户 -P 密码 -c' EXEC master..xp_cmdshell @bcpCommand2 刚刚处理了一个类似的问题,我强烈建议用 c# 编写一个服务/应用程序并改用 SqlBulkCopy,它更加灵活/健壮 【参考方案1】:

为了获得最有效的数据复制方法,您需要做很多事情。到目前为止,你走在正确的轨道上,但你还有很长的路要走。我建议你先看看你的索引。那里可能有一些可以提供帮助的优化。接下来,确保此表上没有可能导致减速的触发器。接下来,更改日志记录级别(如果可以更改)。

这里有更多帮助(来自 Microsoft):

http://msdn.microsoft.com/en-us/library/ms190421(v=SQL.90).aspx

基本上,您使用 BCP 是在正确的轨道上。这其实是微软的建议:

要将数据从一个 SQL Server 实例大容量复制到另一个实例,请使用 bcp 将表数据导出到数据文件中。然后使用其中一种批量导入方法将数据从文件导入到表中。使用本机或 Unicode 本机格式执行批量导出和批量导入操作。

但是,当您这样做时,您还需要考虑如果引入的数据过多(基于您使用的索引类型),是否有可能删除索引。如果您使用聚集索引,那么在导入之前对数据进行排序也是一个好主意。以下是更多信息(包括上述引用的来源):

http://msdn.microsoft.com/en-US/library/ms177445(v=SQL.90).aspx

【讨论】:

感谢 Biggs,这些表没有任何触发器。定义的索引是聚集的。我会在导入之前尝试数据的排序。 我运行了一个测试,使用 bcp out 将记录导出到数据文件,然后使用批量插入将记录导入到 finalTbl。整个过程不到一分钟就完成了。然后我删除了 finalTbl 中的所有索引,这个过程甚至更快。看起来批量插入比 bcp in.. 更快。【参考方案2】:

对于初学者:这些年来我学到的一件事是 MSSQL 在优化各种操作方面做得很好,但要做到这一点在很大程度上依赖于所有相关表的统计信息。因此,我建议在运行实际插入之前运行“UPDATE STATISTICS processes_logs”和“UPDATE STATISTICS unprocessed_logs”;即使在一张大桌子上,这些东西也不会花那么长时间。 除此之外,根据上面的查询,很大程度上取决于目标表的索引。我假设目标表在(至少)UnixTime 上有它的聚集索引(或 PRIMARY KEY),如果没有,当你在现有记录之间挤压越来越多的数据时,你会创建主要的数据碎片。要解决此问题,您可以尝试不时对目标表进行碎片整理(可以在线完成,但需要很长时间),但制作聚集索引(或 PK)以便始终将数据附加到表的末尾会成为更好的方法;好吧,至少在我看来。

【讨论】:

【参考方案3】:

我建议你应该有一个窗口服务并使用计时器和一个布尔变量。一旦你的请求被发送到服务器,将 bool 设置为高位,并且计时器事件不应该执行代码,直到该位为低。

【讨论】:

以上是关于在 SQL Server 2005 中从小表批量复制到大表的主要内容,如果未能解决你的问题,请参考以下文章

批量删除Sql Server对象(表,存储过程,触发器)

SQL Server 2005 中的死锁!两个实时批量更新正在战斗。为啥?

在sql server 2005中使用表数据创建脚本文件[重复]

如何在 SQL Server 2005 中插入值数组?

在 SQL Server 2005 中截断数据库的所有表

sqlserver2005批量替换字符