12

Sono passati un paio di giorni che sto lavorando per migliorare le prestazioni di inserimento di NHibernate.Gli inserimenti della sessione senza stato di NHibernate sono lenti

avevo letto in molti posti (come ad esempio this one) che sessione senza può inserire come 1000 ~ 2000 record al secondo .... Tuttavia, il momento migliore che potrebbe inserire 1243 record è più di 9 secondi per me:

var sessionFactory = new NHibernateConfiguration().CreateSessionFactory(); 
using (IStatelessSession statelessSession = sessionFactory.OpenStatelessSession()) 
{ 
    statelessSession.SetBatchSize(adjustmentValues.Count); 

    foreach (var adj in adjustmentValues) 
     statelessSession.Insert(adj); 
} 

la classe:

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; } 
} 

Mappa della classe:

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(); 
    } 
} 

Mi manca qualcosa? Qualche idea su come velocizzare gli inserti?

enter image description here

Le query generati saranno stessi sotto:

enter image description here

risposta

17

dall'aspetto dei risultati NHProf in cui si utilizza l'identità come POID. Pertanto non è possibile sfruttare le scritture in batch. ogni inserimento/aggiornamento/cancellazione è un comando separato. ecco perché ci vuole così tanto tempo.

se si cambia poid a Hilo, guid o guid.comb e di impostare la dimensione del lotto a 500 o 1000 poi si vedrà un drastico miglioramento nei tempi di scrittura.

4

Sto assumendo si utilizza SQL Server 2008.

Poche cose che vengono in mente. Stai utilizzando la chiave di identità (seleziona SCOPE_IDENTITY() nel tuo output di esempio) come chiave primaria per le tue entità? In caso affermativo, credo che NHibernate debba eseguire la chiamata SCOPE_IDENTITY() per ogni oggetto prima che l'oggetto venga effettivamente salvato nel database. Quindi se stai inserendo 1000 oggetti Nhibernate genererà 1000 istruzioni INSERT e 1000 selezionare le istruzioni SCOPE_IDENTITY().

Non sono sicuro al 100% ma potrebbe anche interrompere il batching. Dato che stai usando NHProf, allora cosa dice? Mostra che tutte le istruzioni sono raggruppate insieme o puoi selezionare una singola istruzione INSERT nell'interfaccia utente NHProf? Se i tuoi inserti non sono in batch, molto probabilmente vedrai l'avviso "Numero elevato di scritture individuali" in NHProf.

Edit:

Se non è possibile modificare la vostra generazione identità allora si potrebbe utilizzare SqlBulkCopy. L'ho usato con NHibernate nella migrazione dei dati e funziona. Ayende Rahien has sample on his blog che ti consente di iniziare.

+0

sì, gli inserimenti sono query separate. –

+1

Per gli inserimenti di massa in cui il tempo conta, vorrei davvero optare per la soluzione 'SQLBulkCopy'. – Rippo

Problemi correlati