Вставки сеанса без состояния NHibernate медленные - PullRequest
12 голосов
/ 19 декабря 2011

Уже пару дней я работаю над улучшением производительности NHibernate Insert.

Я бы прочитал во многих постах (таких как этот ), что сеанс без сохранения состояния может вставлять примерно 1000 ~ 2000 записей в секунду .... Однако лучшее время, когда мог вставить 1243 записи для меня больше, чем за 9 секунд:

var sessionFactory = new NHibernateConfiguration().CreateSessionFactory();
using (IStatelessSession statelessSession = sessionFactory.OpenStatelessSession())
{
   statelessSession.SetBatchSize(adjustmentValues.Count);

   foreach (var adj in adjustmentValues)
      statelessSession.Insert(adj);
}

Класс:

public partial class AdjustmentValue : PersistentObject, IFinancialValue
{
    public virtual double Amount { get; set; }
    public virtual bool HasManualValue { get; set; }
    public virtual bool HasScaleValue { get; set; }
    public virtual string Formula { get; set; }
    public virtual DateTime IssueDate { get; set; }

    public virtual CompanyTopic CompanyTopic { get; set; }
}

Карта класса:

public class AdjustmentValueMap : ClassMap<AdjustmentValue>
{
    public AdjustmentValueMap()
    {
       Id(P => P.Id);

       Map(p => p.Amount);
       Map(p => p.IssueDate);
       Map(p => p.HasManualValue);
       Map(p => p.HasScaleValue);
       Map(p => p.Formula);

       References(p => p.CompanyTopic)
           .Fetch.Join();
    }
}

Я что-то упустил? Есть идеи как ускорить вставки?

enter image description here

Сгенерированные запросы будут такими же, как показано ниже:

enter image description here

Ответы [ 2 ]

18 голосов
/ 19 декабря 2011

Судя по вашим результатам NHProf, вы используете идентичность в качестве POID.Поэтому вы не можете использовать преимущества пакетных записей.каждая вставка / обновление / удаление - это отдельная команда.Вот почему это занимает так много времени.

Если вы измените свой POID на hilo, guid или guid.comb и установите размер пакета на 500 или 1000, тогда вы увидите резкое улучшение времени записи.

5 голосов
/ 19 декабря 2011

Я предполагаю, что вы используете SQL Server 2008.

Мало что приходит на ум. Используете ли вы идентификационный ключ (выберите SCOPE_IDENTITY () в своем примере вывода) в качестве первичного ключа для ваших сущностей? Если да, то я считаю, что NHibernate должен выполнить вызов SCOPE_IDENTITY () для каждого объекта, прежде чем объект будет фактически сохранен в базе данных. Поэтому, если вы вставляете 1000 объектов, Nhibernate сгенерирует 1000 операторов INSERT и 1000 выберет операторы SCOPE_IDENTITY ().

Я не уверен на 100%, но это также может нарушить дозирование. Так как вы используете NHProf, то что это говорит? Показывает ли это, что все операторы объединены или вы можете выбрать отдельный оператор INSERT в пользовательском интерфейсе NHProf? Если ваши вставки не являются пакетными, вы, скорее всего, увидите предупреждение «Большое количество отдельных записей» в NHProf.

Edit:

Если вы не можете изменить генерацию вашей личности, тогда вы можете использовать SqlBulkCopy . Я использовал его с NHibernate в миграции данных, и он работает. У Ayende Rahien есть пример в его блоге , с которого можно начать.

...