SqlBulkCopy 的推荐批量大小是多少?

Posted

技术标签:

【中文标题】SqlBulkCopy 的推荐批量大小是多少?【英文标题】:What is the recommended batch size for SqlBulkCopy? 【发布时间】:2009-04-22 23:38:39 【问题描述】:

SqlBulkCopy 的推荐批量大小是多少?我正在寻找一个通用公式,我可以将其用作性能调整的起点。

【问题讨论】:

【参考方案1】:

我有一个导入实用程序,它与我的 SQL Server 实例位于同一物理服务器上。使用自定义IDataReader,它解析平面文件并使用SQLBulkCopy 将它们插入到数据库中。一个典型的文件有大约 6M 行,平均 5 列十进制和短文本,每行大约 30 个字节。

鉴于这种情况,我发现 5,000 的批量大小是速度和内存消耗的最佳折衷方案。我从 500 开始,然后尝试更大。我发现 5000 平均比 500 快 2.5 倍。插入 600 万行大约需要 30 秒,批量大小为 5000,批量大小为 500 大约需要 80 秒。

10,000 并没有明显更快。提高到 50,000 可以将速度提高几个百分点,但不值得增加服务器上的负载。超过 50,000 则显示速度没有提高。

这不是一个公式,而是您可以使用的另一个数据点。

【讨论】:

要考虑的一件事是表是否为空并且有索引。在这些情况下,您可能希望按照此处所述的批量上传所有内容:technet.microsoft.com/en-us/library/ms177445(v=sql.105).aspx“如果您将数据批量导入带有索引的空表并指定批量大小,则该表在第一批后变为非空。开始对于第二批,数据是完整记录的。对于空索引表,请考虑在单个批次中执行批量导入。" SqlBulkCopy 将数据从源(例如 DataTable)流式传输到 Sql,那么在大批量大小上它有什么“增加的服务器负载”? (例如 50,000)【参考方案2】:

这是一个我也花了一些时间研究的问题。我希望使用 C# 控制台应用程序 (.Net 2.0) 优化将大型 CSV 文件(16+ GB、65+ 百万条记录,并且还在增长)导入 SQL Server 2005 数据库。由于Jeremy 具有already pointed out,您需要针对您的特定情况进行一些微调,但我建议您将初始批量大小设置为 500,并测试高于和低于此值的值。

我从这个MSDN forum post 得到了测试批量大小在 100 到 1000 之间的值的建议,我对此表示怀疑。但是当我测试 100 到 10,000 之间的批量大小时,我发现 500 是我的应用程序的最佳值。 SqlBulkCopy.BatchSize 的 500 值也推荐 here。

要进一步优化您的 SqlBulkCopy 操作,请查看此MSDN advice;我发现使用 SqlBulkCopyOptions.TableLock 有助于减少加载时间。

【讨论】:

我认为在服务器本身运行批量复制命令可能会更快。【参考方案3】:

正如其他人所说,这取决于您的环境,特别是行容量和网络延迟。

就我个人而言,我会先将BatchSize 属性设置为1000 行,然后看看效果如何。如果可行,那么我会继续将行数加倍(例如增加到 2000、4000 等),直到超时。

否则,如果在 1000 处发生超时,那么我将行数减少一半(例如 500),直到它起作用为止。

在每种情况下,我都会将最近两次尝试的批量大小之间的差异加倍(如果成功)或减半(如果失败),直到找到最佳位置。

另一个要考虑的因素是复制单个 批行需要多长时间。如果正在复制的行批次超过BulkCopyTimeout 属性(默认为 30 秒),则会发生超时。您可以尝试将 BulkCopyTimeout 属性加倍到 60 秒。这允许复制更大的批次行集的时间更长。例如,一批 50,000 行可能需要大约 40 秒,刚好超过 30 秒的时间限制,因此将其提高到 60 秒可能有助于提高性能。

【讨论】:

【参考方案4】:

这一切都取决于您的实施。

您的网络可以达到什么样的速度? 您是在 Forms 还是 ASP.Net 中使用它? 您是否需要提醒用户进度? 整个作业的大小是多少?

根据我的经验,在没有指定批量大小的情况下运行批量复制会导致超时问题。我喜欢从 1000 条记录开始,然后从那里做一些调整。

【讨论】:

速度:变化,WebForms:是,ASP.NET:是,宽表:是,窄表,是。千行:是的。数百万行:是的。如果你能想到一个场景,我可能正在做。 那我必须坚持我之前的回答。我认为没有灵丹妙药。【参考方案5】:

@Alric 建议的价值观对我来说似乎过于保守了。

作为我正在处理的项目的一部分,我刚刚尝试了 10,000、100,000 和 1,000,000 的批量大小。我的目标表是聚集列存储 bigint、int、int、int、date、decimal(32,15)。

BatchSize
10,000       100,000      1,000,000
3:31:25 PM   3:28:43 PM   3:36:57 PM
3:35:24 PM   3:29:38 PM   3:37:44 PM
3.983333332  0.916666671  0.783333328    (minutes)

5 秒刷新时的 SSMS 活动监视器显示此数据库的写入速度 感觉对我来说很低,但我真的不知道如何准确地校准我的期望。

【讨论】:

amonroejj 如果我们做类似new SqlBulkCopy(connection) BatchSize = numberOfRows, // could be 1M or 10M DestinationTableName = "dbo.Contacts" ;的事情会发生什么 知道会发生什么的唯一方法就是尝试看看。【参考方案6】:

我尝试了多种尺寸,在我的情况下 5000 就很好

【讨论】:

以上是关于SqlBulkCopy 的推荐批量大小是多少?的主要内容,如果未能解决你的问题,请参考以下文章

SqlServer批量复制(bcp)[C#SqlBulkCopy]性能极低问题

用SqlBulkCopy批量插入数据 遇到的错误

您如何确定现实世界中推荐的 ADO.NET 批量大小?

对于 django/PostgreSQL DB - 推荐的最大对象大小应该是多少?

SqlBulkCopy简单封装,让批量插入更方便

批量插入 SqlBulkCopy的测试