12

我正在努力改进NHibernate插入性能已经有好几天了。NHibernate的无状态会话插入很慢

我在很多职位(如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

回答

17

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

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

4

我假设你使用的是SQL Server 2008的

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

我不是100%确定,但它也可能打破配料。既然你使用NHProf,那么它说什么?它是否显示所有的语句是一起批处理的,还是可以在NHProf UI中选择单独的INSERT语句?如果您的插入没有批处理,那么您很可能会在NHProf中看到“大量的单个写入”警报。

编辑:

如果你不能改变你的身份代,那么你可以使用SqlBulkCopy。我用NHibernate在数据迁移中使用它,它可以工作。 Ayende Rahien has sample on his blog让你开始。

+0

是的,插入是单独的查询。 – 2011-12-19 16:02:34

+1

对于时间很重要的批量插入,我真的会去'SQLBulkCopy'解决方案。 – Rippo 2011-12-20 10:58:02