2010-08-25 97 views
6

我终于得到我的插入批处理工作,现在我一直在摆弄批处理的大小,但我看不到50之间的值和10000的值之间的性能差异。这似乎很对我来说很奇怪,但我不知道幕后发生了什么,所以这可能是正常的行为。如何将DataAdapter.UpdateBatchSize设置为“最佳”值?

我将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问题和即将插入的数据,那么不应该有可能计算或至少猜测一个好的价值吗?

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

回答

5

您可以通过查看SQL事件探查器或致电SqlConnection.RetrieveStatistics()来查看批处理的效果。你应该看到每个批次对应于一次往返数据库。

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

可达到的速度通常首先受到往返次数的限制,然后是事务大小,然后记录磁盘速度(特别是顺序访问是可能的还是强制随机由于与同一主轴上的其他文件竞争),最后是RAM。但是,所有这些因素在一定程度上也是相互关联的。

改善插入性能的第一步是在交易中完成它们 - 也许每一批或两批交易一次。除此之外,表值参数可能是下一步,使用存储过程INSERT INTO Table SELECT column FROM @TableArgument

1

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

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

0

确保还有一个活动事务,它会极大地提高性能(在使用MysqlDataAdapter进行的测试中大约为30倍)。

相关问题