在 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 的新手,遇到以下困境:
我有两个结构相同的表。称它为runningTbl
和finalTbl
。
runningTbl
每 15 分钟包含大约 600 000 到 100 万行。
在runningTbl
中进行一些数据清理后,我想将所有记录移动到finalTbl
。
finalTbl
目前大约有 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 2005 中的死锁!两个实时批量更新正在战斗。为啥?