无状态NHibernate会话的插入很慢

时间:2011-12-19 14:56:37

标签: c# nhibernate fluent-nhibernate bulkinsert stateless-session

我正在努力改进NHibernate Insert性能。

我在很多帖子(例如this one)中读到无状态会话可以插入每秒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 个答案:

答案 0 :(得分:18)

从您的NHProf结果看起来您使用身份作为您的POID。因此,您无法利用批量写入。每个插入/更新/删除都是一个单独的命令。这就是为什么花了这么长时间。

如果您将POID更改为hilo,guid或guid.comb并将批量大小设置为500或1000,那么您将看到写入时间的显着改善。

答案 1 :(得分:5)

我假设您使用的是SQL Server 2008。

很少有想到的事情。您是否使用身份密钥(在示例输出中选择SCOPE_IDENTITY())作为实体的主键?如果是,那么我相信NHibernate必须在对象实际保存到数据库之前对每个对象执行SCOPE_IDENTITY()调用。因此,如果要插入1000个对象,Nhibernate将生成1000个INSERT语句和1000个选择SCOPE_IDENTITY()语句。

我不是百分百肯定,但它也可能打破批处理。既然您正在使用NHProf那么它会说什么?是否显示所有语句都已批处理,或者您是否可以在NHProf UI中选择单独的INSERT语句?如果您的插入没有批处理,那么您很可能会在NHProf中看到“大量个人写入”警报。

编辑:

如果您无法更改身份生成,则可以使用SqlBulkCopy。我在NHibernate中使用它进行数据迁移,它可以工作。 Ayende Rahien has sample on his blog让你开始。