如何将DataAdapter.UpdateBatchSize设置为“最佳”值?

时间:2010-08-25 12:24:40

标签: performance ado.net updatebatchsize

我终于让我的插件批量工作了,现在我一直在摆弄批量的大小,但是我看不到值50和值10000之间的性能差异。这似乎对我来说很奇怪,但我不知道幕后发生了什么,所以这可能是正常行为。

我在表中插入160k行,测试值的平均时间为115 +/- 2秒。没有批处理需要210秒,所以我对改进非常满意。目标表是:

CREATE TABLE [dbo].[p_DataIdeas](
    [wave] [int] NOT NULL,
    [idnumber] [int] NOT NULL,
    [ideaID] [int] NOT NULL,
    [haveSeen] [bit] NOT NULL CONSTRAINT [DF_p_DataIdeas_haveSeen]  DEFAULT ((0)),
  CONSTRAINT [PK_p_DataIdeas] PRIMARY KEY CLUSTERED 
(
  [wave] ASC,
  [idnumber] ASC,
  [ideaID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON
) ON [PRIMARY]
) ON [PRIMARY]

我读了What to look for when setting UpdateBatchSize,答案是简单地测试几个不同的值。我能理解这一点,但如果您知道表格设计,SQL问题和即将插入的数据,那么不应该计算或至少猜测一个好的值吗?

有没有人可以推荐的最佳做法?

3 个答案:

答案 0 :(得分:6)

您可以通过查看SQL事件探查器或调用SqlConnection.RetrieveStatistics()来查看批处理的效果。您应该看到的是,每个批次对应于DB的单次往返。

就如何优化批量大小而言,一个非常粗略的经验法则是,当批量大小超过50时,性能往往会停止提高 - 实际上,有时较大批次的运行速度可能比较小批次慢。如果我太忙而无法测试,我通常会从大约20个批次开始(除非我使用表值参数,其中批量最多500个可以比较小的批次快)。但是,最佳数量取决于插件的总大小(它们是否都适合RAM),数据库日志所在磁盘的速度,日志是否位于其自身的驱动器/ LUN上(如果不是那么大的成本,等等。

可实现的速度通常首先受到往返次数的限制,然后是交易大小,然后记录磁盘速度(特别是是否可以顺序访问,或者由于与其他文件的竞争而被迫随机访问)相同的主轴),最后是RAM。但是,所有因素在某种程度上也是相互关联的。

提高插入性能的第一步是在事务中执行它们 - 可能每批次或两次交易。除此之外,表值参数可能是下一步,使用带INSERT INTO Table SELECT column FROM @TableArgument的存储过程。

答案 1 :(得分:1)

尽管更改UpdateBatchSize在某种程度上有所帮助,但使用DataAdapter更新大量记录的基本方法将会很慢。这是因为最终,DataAdapter将为每一行生成单独的SQL语句(插入,更新或删除)。 UpdateBatchSize仅影响在发送到SQL Server时在一个TSQL批处理中发送的单个语句的数量。

要获得更大的性能改进,您希望SQLServer在一个语句中插入/更新/删除许多记录(通常使用某种类型的JOIN)。表值参数(如RickNZ所述)是这样做的一种方式。另一种可能性是使用SqlBulkCopy(尽管您通常需要使用临时表)。

答案 2 :(得分:0)

确保还有一个活动事务,它将大大提高性能(在我使用MysqlDataAdapter的测试中大约30倍)。