Вставки сеанса без состояния NHibernate медленные
Уже пару дней я работаю над улучшением производительности 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();
}
}
Я что-то пропустил? Есть идеи как ускорить вставки?
Сгенерированные запросы будут такими же, как показано ниже:
2 ответа
Судя по вашим результатам NHProf, вы используете идентификацию в качестве POID. Поэтому вы не можете использовать преимущества пакетных записей. каждая вставка / обновление / удаление - это отдельная команда. вот почему это занимает так много времени.
если вы измените свой POID на hilo, guid или guid.comb и установите размер пакета 500 или 1000, тогда вы увидите значительное улучшение во времени записи.
Я предполагаю, что вы используете SQL Server 2008.
Мало что приходит на ум. Используете ли вы идентификационный ключ (выберите SCOPE_IDENTITY() в своем примере вывода) в качестве первичного ключа для ваших сущностей? Если да, то я считаю, что NHibernate должен выполнить вызов SCOPE_IDENTITY() для каждого объекта, прежде чем объект будет фактически сохранен в базе данных. Поэтому, если вы вставляете 1000 объектов, Nhibernate сгенерирует 1000 операторов INSERT и 1000 выберет операторы SCOPE_IDENTITY().
Я не уверен на 100%, но это также может нарушить дозирование. Так как вы используете NHProf, то что он говорит? Показывает ли это, что все операторы объединены или вы можете выбрать отдельный оператор INSERT в пользовательском интерфейсе NHProf? Если ваши вставки не пакетированы, вы, скорее всего, увидите предупреждение "Большое количество отдельных записей" в NHProf.
Редактировать:
Если вы не можете изменить свою идентификацию, вы можете использовать SqlBulkCopy. Я использовал его с NHibernate в миграции данных, и он работает. У Ayende Rahien есть пример в его блоге, с которого можно начать.