12

Han pasado un par de días trabajando para mejorar el rendimiento de la inserción de NHibernate.Las inserciones de la sesión sin estado de NHibernate son lentas

que había leído en muchos mensajes (tales como this one) que sesión sin puede insertar como 1000 ~ 2000 registros por segundo .... Sin embargo, el mejor momento que podría insertar los registros de 1243 es de más de 9 segundos para me:

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

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

la clase:

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

Mapa de la clase:

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

¿Me está faltando algo? ¿Alguna idea de cómo acelerar los insertos?

enter image description here

Las consultas generadas serán iguales que abajo:

enter image description here

Respuesta

17

por el aspecto de los resultados de su NHProf usted está utilizando la identidad como su POID. Por lo tanto, no puede aprovechar las escrituras por lotes. cada inserción/actualización/eliminación es un comando separado. es por eso que lleva tanto tiempo.

si cambia su POID a hilo, guid o guid.comb y configura el tamaño del lote a 500 o 1000, entonces verá una mejora drástica en los tiempos de escritura.

4

Asumo que está utilizando SQL Server 2008.

Pocas cosas que vienen a la mente. ¿Está utilizando la clave de identidad (seleccione SCOPE_IDENTITY() en su resultado de muestra) como clave principal para sus entidades? En caso afirmativo, entonces creo que NHibernate debe ejecutar la llamada SCOPE_IDENTITY() para cada objeto antes de que el objeto se guarde realmente en la base de datos. Entonces, si está insertando 1000 objetos, Nhibernate generará 1000 declaraciones INSERT y 1000 declaraciones select SCOPE_IDENTITY().

No estoy 100% seguro, pero también podría romper el procesamiento por lotes. Como está utilizando NHProf, ¿qué dice? ¿Muestra que todas las declaraciones están agrupadas o puede seleccionar una declaración INSERT individual en la interfaz de usuario de NHProf? Si sus insertos no están agrupados, lo más probable es que vea una alerta de "Número grande de escrituras individuales" en NHProf.

Editar:

Si no puede cambiar su identidad generación entonces se podría utilizar SqlBulkCopy. Lo he usado con NHibernate en migración de datos y funciona. Ayende Rahien has sample on his blog que te permite comenzar.

+0

sí, las inserciones son consultas separadas. –

+1

Para inserciones masivas donde el tiempo importa, realmente iría por la solución 'SQLBulkCopy'. – Rippo

Cuestiones relacionadas