使用NHibernate加速批量插入操作

dea*_*mon 16 .net oracle nhibernate performance orm

我想insert在Oracle 11g上加速NHibernate 3.2的批量操作.为此,我试过了

Session.Save(entity);
Session.Flush();
Session.Clear();
Run Code Online (Sandbox Code Playgroud)

...在我的foreach循环中但由于会话中缺少对象而导致异常:

未能懒惰地初始化角色集合:MyClass.PropertyX,没有关闭会话或会话

另一种尝试是设置批量大小:

<hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
  <session-factory>
    <property name="connection.provider">NHibernate.Connection.DriverConnectionProvider</property>
    <property name="connection.driver_class">NHibernate.Driver.OracleClientDriver</property>
    <property name="connection.connection_string">xxx</property>
    <property name="dialect">NHibernate.Dialect.Oracle10gDialect</property>
    <property name="adonet.batch_size">50</property>
    <property name="query.substitutions">true=1, false=0</property>
    <property name="proxyfactory.factory_class">NHibernate.Bytecode.DefaultProxyFactoryFactory, NHibernate</property>
  </session-factory>
</hibernate-configuration>
Run Code Online (Sandbox Code Playgroud)

另外我Session.SetBatchSize(50)在我的代码中设置了以下异常:

没有为会话工厂定义批量大小,禁用批处理.设置adonet.batch_size = 1以启用批处理.

抛出此异常的唯一位置是NonBatchingBatcher,因此看起来我的会话有错误的batcher.

这有什么不对?如何使用NHibernate加速批量插入(不使用statlese会话)?

Low*_*can 39

以下应该工作,

var testObjects = CreateTestObjects(500000);

var stopwatch = new Stopwatch();
stopwatch.Start();
using (IStatelessSession session = sessionFactory.OpenStatelessSession())
using (ITransaction transaction = session.BeginTransaction())
{
    foreach (var testObject in testObjects)
        session.Insert(testObject);
    transaction.Commit();
}

stopwatch.Stop();
var time = stopwatch.Elapsed;
Run Code Online (Sandbox Code Playgroud)

参考:http://nhibernate.info/blog/2008/10/30/bulk-data-operations-with-nhibernate-s-stateless-sessions.html


Dav*_*Dav 5

以上所有技巧都是非常有效和有用的。想要向集合中添加一个:禁用日志记录。在控制台中显示SQL会显着降低您的速度,使用NHProf进行性能分析,自动注释和通过NLog或log4net记录SQL的漂亮格式也会显着降低您的速度。在我们的情况下:

cfg.AutoCommentSql = false;
cfg.LogFormattedSql = false;
Run Code Online (Sandbox Code Playgroud)

将批量插入时间从〜6秒减少到刚刚超过1秒。因此,尽管日志记录有可能帮助您解决更严重的问题,但它本身具有性能上的优势!


ber*_*sch 1

为什么要清除会话?

我认为你不应该清除循环中的会话。为了确保更改写入数据库,我宁愿使用事务。

伪代码:

foreach (var i in allElements)
{
    using (var tx = session.BeginTransaction())
    {
        ... do what you have to do with the object
        tx.Commit();
    }
}
Run Code Online (Sandbox Code Playgroud)

为了加快速度,还有其他一些可能有帮助的事情 - 你必须定义你真正想在循环中做什么。