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

标签 c# nhibernate

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

我想检查这些程序的性能,因此我创建了一些测试来输入大量数据并让进程执行它们的操作。其中 2 个过程的结果让我很困惑。

第一个是一个相当简单的案例,即对 XML 文件中提供的数据进行一些简单处理并将其导入。 XML 包含大约 172,000 行,该过程总共需要大约 60 秒才能运行,实际插入大约需要 40 秒。

在接下来的过程中,我对同一组数据做一些处理。所以我有一个数据库,在一个表中有大约 172,000 行。然后该过程处理这些数据,进行一些更繁重的处理并生成一大堆数据库更新(对同一个表的插入和更新)。 总的来说,这导致插入了大约 50,000 行并更新了 80,000 行。 在这种情况下,处理大约需要 30 秒,这很好,但是将更改保存到数据库需要 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); }
});

(尽管第一个进程没有“transToUpdate”行,因为它只是插入 - 删除更新行并仅执行插入仍然需要将近 10 分钟。) transTo* 变量是包含要更新/插入的对象的列表。

BulkDataInsert 创建 session 并处理数据库事务。

最佳答案

我不明白你的第二个过程。但是,这里有一些需要考虑的事项:

  1. 表上是否有聚簇索引或非聚簇索引?
  2. 您有多少个磁盘驱动器?
  3. 在第二个测试中有多少线程正在写入数据库?

看来您遇到了 IO 瓶颈,可以通过拥有更多磁盘、更多线程、索引等来解决。

所以,假设很多事情,这就是我“认为”正在发生的事情:

  1. 在第一个测试中,您的表可能没有索引,并且由于您只是插入数据,因此它是在单个线程中的顺序插入,速度可能非常快 - 特别是如果您正在写入一个磁盘。
  2. 现在,在第二个测试中,您正在读取数据,然后更新数据。您的 SQL 实例必须找到它需要更新的记录。如果您没有任何索引,这个“查找”操作基本上是一个表扫描,对于这 80,000 行更新中的每一个都会发生。这将使您的应用程序变得非常非常慢。

您可能做的最简单的事情是在表上为唯一键添加聚集索引,最好的选择是使用您在 where 子句中使用的列来“更新”那些行。

希望这对您有所帮助。

免责声明:我做了很多假设

关于c# - 什么会影响 nhibernate 批量插入性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13956473/

相关文章:

c# - Spring.NET - 对象引用未设置为对象的实例

c# - 如何生成交易号?

c# - 如何删除代码中的所有注释?

c# - 在安卓上找不到路径

c# - 如何在 Fluent-NHibernate 中级联插入父级、子级和组合列表

c# - 如何防范 NHibernate 不完整映射

c# - SQLite 是否与 Entity Framework 配合良好?

c# - 更改列表框中一个列表项的背景(不是所选项目)

wpf - 如何在 WPF 应用程序中限定 NHibernate session 和事务

NHibernate SchemaExport 无法删除表 .... 有时