4

基于此处提出的想法,我创建了一个QueuedDataReader将 a 包装ConcurrentQueue在 an 中的方法,IDataReader以便我可以将其传递给SqlBulkCopy数据库并将数据“流式传输”到数据库中。

它工作正常,而且速度非常快,但日志文件增长非常快,尽管我相信我已经实现了这里这里(以及许多其他地方)建议的所有内容。

两个可能很重要的细节是:

  • 我正在并行插入十几个表(即Task每个表一个)
  • 这些表有IDENTITY列(SqlBulkCopy 没有插入其中),所以我不认为“排序”附带条件是相关的。

在此之上:

  • 当我开始插入时,表格是空的。
  • 我已经在 PRIMARY KEY 上尝试了 CLUSTERED 和 NONCLUSTERED 索引,没有太大的可观察到的差异。
  • 我在用着SqlBulkCopyOptions.TableLock
  • 我尝试过使用和不使用 UseInternalTransactions 和各种 BatchSizes。
  • 数据库处于简单恢复模式
  • 这些表确实有 FK 约束,但我尝试禁用/重新启用它们并且它不会停止日志文件的增长(在插入期间)

问题:

  • 我可以查看哪些内容来尝试解决可能导致日志文件增长的问题?
4

1 回答 1

0

在写我的问题时,我在这里发现了另一个优秀的资源,它指出 BatchSize 是潜在的罪魁祸首。

结果相当令人惊讶。如果我们使用 BatchSize 参数,当我们将其设置为较低的值时,性能会变得越来越差。

使用非常小的批大小值,网络带宽在整个过程中保持在 20% 以下(请注意,500 批大小图表上限为 25%,这与其他图表不同)。任何低于 10.000 的值都会以非常严重的方式降低性能,从而导致时间非常短并且日志文件使用量很大。

当我们达到 10.000 的 Batch Size 时,各种测试之间的时间差异变得非常小。但是,由于我们有 8 个线程,每个线程写入 750.000 行,那么每个线程只发送 75 个数据块。不用说,当我们使用 0 作为 BatchSize 时获得最佳性能,在单个批次中发送整个 750.000 行。

通过使用 BatchSize 参数发现除了性能之外是否还有其他好处可能会很有趣。我们没有发现在线书籍中提到的任何内容,也没有在我们的体验中看到任何有趣的东西,这导致我们说,使用 BatchSize 的最佳方法是将其保留为零,这是它的默认值,因为任何与此不同的值将降低加载过程的性能。

我之前BatchSize = 0因为超时错误而放弃了,但是通过将 my 设置BulkCopyTimeout为零,我得到了一些日志文件增长,但远低于以前。

更新。在搞了太久的手动测试之后,我终于开始着手编写一个自动化测试套件,尝试 BatchSize(0-5000)、排队率和聚集/非聚集索引的变体。(就我而言,我正在将数据并行写入十几个表)。

这是我发现的:

  • 200000 次插入的测试:如果主键是CLUSTERED BatchSize 为零,我不会得到日志文件增长。
  • 100 万次插入的测试:即使 BatchSize=0,日志文件也会增长(尽管比其他 BatchSize 少得多)。CLUSTERED无论 BatchSize 是多少,仍然可以防止日志增长。
  • 在这些条件之外,一切都取决于插入速度。一旦我“推”得太用力,日志文件就会开始增长。

请注意,我的测试以给定的速率将数据写入包装在 IDataReader 中的队列中,该队列由 BulkInsert 出列。每个表一个队列/BulkInsert。下一步是尝试使用更大的数据集。

于 2013-10-28T12:06:41.667 回答