Подтвердить что ты не робот

Ускорьте объемные операции вставки с помощью NHibernate

Я хочу ускорить массовые операции insert с NHibernate 3.2 на Oracle 11g. Для этого я попробовал

Session.Save(entity);
Session.Flush();
Session.Clear();

... в моем цикле 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>

Кроме того, я установил Session.SetBatchSize(50) в свой код и получил следующее исключение:

Размер сеанса не определен для сеанса factory, пакетная обработка отключен. Установите adonet.batch_size = 1 для включения пакетной обработки.

Единственное место, где выбрано это исключение, - это NonBatchingBatcher, поэтому похоже, что мой сеанс имеет неправильный дозатор.

Что здесь не так? Как ускорить пакетные вставки с помощью NHibernate (без использования сеансов statlese)?

4b9b3361

Ответ 1

Следующее должно работать,

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;

Ссылка: http://nhibernate.info/blog/2008/10/30/bulk-data-operations-with-nhibernate-s-stateless-sessions.html

Ответ 3

Все приведенные выше советы очень полезны и очень полезны. Требуется добавить его в коллекцию: отключить ведение журнала. Наличие вашего SQL, показанного на консоли, заметно замедляет вас, как и профилирование с использованием NHProf, автоматическое комментирование и довольно-форматирование SQL, зарегистрированного через NLog или log4net. В нашем случае установка:

cfg.AutoCommentSql = false;
cfg.LogFormattedSql = false;

уменьшилось время вставки вставки от ~ 6 секунд до чуть более 1 секунды. Поэтому, в то время как ведение журнала потенциально поможет вам решить более серьезные проблемы, у вас есть собственный успех!

Ответ 4

Почему вы очищаете сеанс?

Я думаю, вы не должны очищать сеанс в цикле. Чтобы убедиться, что изменения записаны в базу данных, я предпочел бы использовать транзакцию.

псевдокод:

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

Чтобы ускорить работу, есть другие вещи, которые могут помочь - вы должны определить, что вы действительно хотите сделать в цикле.

Ответ 5

Я знаю, что вопрос был о Oracle, но для SQL-сервера я собирался написать процедуру, чтобы отображать сопоставления классов и генерировать DataTable, который будет использоваться SqlBulkInsert, но я узнал, что кто-то уже это сделал.

https://kaylaniam.wordpress.com/2015/03/13/nhibernate-and-sqlbulkcopy/

Это, вероятно, самый быстрый способ делать массовые вставки на SQL Server.