什么会影响nhibernate批量插入性能?

Ste*_*eve 5 c# nhibernate

我在基于c#和Fluent NHibernate构建的项目中有各种大型数据修改操作.DB是sqlite(在磁盘上而不是在内存中,因为我对性能感兴趣)

我想检查这些的性能,所以我创建了一些测试来提供大量数据并让流程做他们的事情.其中2个过程的结果让我非常困惑.

第一个是一个相当简单的例子,它采用XML文件中提供的数据进行一些轻量处理并导入它.XML包含大约172,000行,并且该过程总共需要大约60秒才能运行,实际插入大约需要40秒.

在下一个过程中,我对同一组数据进行一些处理.所以我在一个表中有一个大约172,000行的数据库.然后,该过程将处理此数据,执行一些较重的处理并生成一大堆数据库更新(插入和更新到同一个表).总的来说,这会导致插入大约50,000行并更新80,000行.在这种情况下,处理大约需要30秒,这很好,但保存对DB的更改需要30分钟!并且它在用sqlite'磁盘或i/o错误完成之前崩溃'

所以问题是:为什么第二个进程中的插入/更新速度要慢得多?它们使用相同的连接在同一个数据库的同一个表上工作.在这两种情况下,都使用IStatelessSession,ado.batch_size设置为1000.

在这两种情况下,代码看起来都像这样执行更新:

BulkDataInsert((IStatelessSession session) =>
{
    foreach (Transaction t in transToInsert) { session.Insert(t); }
    foreach (Transaction t in transToUpdate) { session.Update(t); }
});
Run Code Online (Sandbox Code Playgroud)

(虽然第一个进程没有'transToUpdate'行,因为它只是插入 - 删除更新行只是进行插入仍然需要大约10分钟.)transTo*变量是List,包含要更新/插入的对象.

BulkDataInsert创建会话并处理数据库事务.

Ste*_*eve 0

问题是由于我的测试设置造成的。正如基于 nhibernate 的项目很常见的那样,我一直在使用内存中的 sqlite 数据库进行单元测试。这些工作很好,但一个缺点是,如果关闭会话,它会破坏数据库。因此,我的工作单元实现包含一个“PreserveSession”属性来保持会话处于活动状态,并在需要时创建新事务。

我的新性能测试使用磁盘数据库,但它们仍然使用通用代码来设置测试数据库,因此将 PreserveSession 设置为 true。

似乎让多个会话全部保持打开状态(即使它们没有执行任何操作)一段时间后就会开始导致问题,包括性能下降和磁盘 IO 错误。

我在 PreserveSession 设置为 false 的情况下重新运行了第二个测试,结果立即从 30 多分钟降至不到 2 分钟。这更符合我的预期。