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