负载下插入性能提高:为什么?

mah*_*nya 19 sql-server sql-server-2008-r2

我有一段代码可以执行插入到高度非规范化的表中。这些表的列数从 ~100 到 300+ 不等。这是 SQL Server 2008 R2,在 Windows Server 2008 上运行。

每个插入包括插入到同一事务下的多个表。有些插入是由 NHibernate 批处理的,但有些不能,但它们都在同一个事务下。

当我通过重复调用一段执行插入的代码来执行插入 500 次时,我得到平均约 360 毫秒。

奇怪的是,当我使用 4 个进程(在 Windows Server 2008 下从 4 个不同的命令提示符运行相同的 exe)同时运行测试代码时,每次调用的插入性能变得更好。我看到突发速度高达 90 毫秒(快了几乎 X4)。我正在测量代码中的插入时间。

由于这 4 个进程彼此一无所知,我假设这与 SQL Server 有关,但我完全不知道为什么。我想知道为什么会发生这种情况,以及是否有任何配置可以让我在插入不那么频繁的情况下获得相同的性能。

同样欢迎有关 SQL Server 监视方法以了解数据库级别发生的情况的建议。

Pau*_*ite 15

一个可能的原因是四个并发进程生成了更有利的日志刷新模式 - 通常意味着每个日志刷新写入的数据比单个执行进程的情况多。

要确定事务日志吞吐量/刷新大小是否是一个因素,请监视:

寻找达到的内部限制。在 SQL Server 2008 R2 中,每个数据库在 64 位版本上最多可以有 32 个未完成的(异步)日志刷新 I/O(在 32 位上只有 8 个)。未完成 IO 的总大小也有 3840KB 的限制。

更多信息和进一步阅读:


Rob*_*ley 12

@PaulWhite 所说的一切,加上...

如果您有外键,则每次插入都需要对引用的每个表进行检查。对我来说听起来像你一样,因为你只有 360 毫秒,这对我来说感觉很慢。

无论如何,检查这些表对检查这些表有很大帮助,因为这些数据已经存在于 RAM 中,而不必将其加载到磁盘中。

在我看来,将数据加载到 RAM 中是执行的重要部分,而且它只需要发生一次。

它也可能是有效的计划缓存,并且您的查询需要第一次编译,随后的调用可以避免该阶段。

  • @mahonya,即使您没有明确地将数据加载到 RAM 中,SQL Server 也必须先将所需的索引和数据页读入缓冲区缓存,然后再执行插入操作。并发插入线程可能具有预热缓存的效果,使得一个线程产生读取开销,而另一个线程访问缓存中的数据。 (2认同)