无状态NHibernate会话的插入很慢
我正在努力改进NHibernate Insert性能已经有几天了。
我在许多post(例如这篇文章)中读到无状态会话可以插入每秒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); }
class级 :
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; } }
class级地图:
public class AdjustmentValueMap : ClassMap { 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(); } }
我错过了什么吗? 知道如何加快插入速度吗?
生成的查询将与以下内容相同:
从您的NHProf结果看起来,您使用身份作为您的POID。 因此,您无法利用批量写入。 每个插入/更新/删除都是一个单独的命令。 这就是为什么它需要这么长时间。
如果您将POID更改为hilo,guid或guid.comb并将批量大小设置为500或1000,那么您将看到写入时间的显着改善。
我假设你使用的是SQL Server 2008。
想到的事情很少。 您是否使用身份密钥(在示例输出中选择SCOPE_IDENTITY())作为实体的主键? 如果是,那么我相信NHibernate必须在对象实际保存到数据库之前对每个对象执行SCOPE_IDENTITY()调用。 因此,如果要插入1000个对象,Nhibernate将生成1000个INSERT语句和1000个选择SCOPE_IDENTITY()语句。
我不是百分百肯定,但它也可能打破批处理。 既然你正在使用NHProf那么它说的是什么? 是否显示所有语句都已批处理,或者您是否可以在NHProf UI中选择单独的INSERT语句? 如果您的插入没有批处理,那么您很可能会在NHProf中看到“大量个人写入”警报。
编辑:
如果您无法更改身份生成,则可以使用SqlBulkCopy 。 我在NHibernate中使用它进行数据迁移并且它可以工作。 Ayende Rahien在他的博客上有样本可以帮助你入门。