8

我终于让我的插入批次工作了,现在我一直在摆弄批次的大小,但我看不出值 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]

我阅读了设置 UpdateBatchSize 时要查找的内容,答案是简单地测试几个不同的值。我可以理解,但是如果您知道表设计、SQL 问题和即将插入的数据,是否应该可以计算或至少猜测一个好的值?

有没有人可以推荐的最佳实践?

4

3 回答 3

8

您可以通过查看 SQL Profiler 或调用SqlConnection.RetrieveStatistics(). 您应该看到的是,每个批次对应于到数据库的一次往返。

至于如何优化批量大小,一个非常粗略的经验法则是,当批量大小超过 50 左右时,性能往往会停止改进——事实上,有时大批量比小批量运行得更慢。如果我太忙而无法测试,我通常从大约 20 个批次开始(除非我使用表值参数,其中最多 500 个的批次可能比较小的批次更快)。但是,最佳数量取决于插入的总大小(它们是否都适合 RAM)、数据库日志所在磁盘的速度、日志是否在其自己的驱动器/LUN 上(如果不是,则需要很大的性能成本)等。

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

提高插入性能的第一步是在事务中执行它们——也许每批或两批一个事务。除此之外,表值参数可能是下一步,使用带有INSERT INTO Table SELECT column FROM @TableArgument.

于 2011-12-02T15:12:57.477 回答
1

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

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

于 2011-12-03T00:22:51.280 回答
0

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

于 2015-06-11T13:38:35.603 回答