Pregunta

Tengo una aplicación que usa NHibernate como ORM y, a veces, experimenta problemas de rendimiento debido a la forma en que accede a los datos.¿Qué tipo de cosas se pueden hacer para mejorar el rendimiento de NHibernate?(Limítese a una recomendación por respuesta)

¿Fue útil?

Solución

El primer y más dramático problema de rendimiento con el que puede encontrarse con NHibernate es si está creando una nueva fábrica de sesiones para cada sesión que cree.Solo se debe crear una instancia de fábrica de sesiones para cada ejecución de aplicación y todas las sesiones deben ser creadas por esa fábrica.

En ese sentido, debes continuar usando la misma sesión siempre que tenga sentido.Esto variará según la aplicación, pero para la mayoría de las aplicaciones web, se recomienda una única sesión por solicitud.Si desechas tu sesión con frecuencia, no obtendrás los beneficios de su caché.El uso inteligente del caché de sesión puede cambiar una rutina con un número lineal (o peor) de consultas a un número constante sin mucho trabajo.

Igualmente importante es que quieras asegurarte de que eres lento al cargar las referencias de tus objetos.Si no es así, se podrían cargar gráficos de objetos completos incluso para las consultas más simples.Sólo hay ciertas razones para no hacer esto, pero siempre es mejor comenzar con la carga diferida y volver a cambiar según sea necesario.

Eso nos lleva a la búsqueda ansiosa, lo opuesto a la carga diferida.Al atravesar jerarquías de objetos o recorrer colecciones, puede ser fácil perder la cuenta de cuántas consultas está realizando y terminar con un número exponencial de consultas.La búsqueda ansiosa se puede realizar por consulta con FETCH JOIN.En circunstancias excepcionales, como si hay un par particular de tablas a las que siempre busca unirse, considere desactivar la carga diferida para esa relación.

Como siempre, SQL Profiler es una excelente manera de encontrar consultas que se ejecutan con lentitud o que se realizan repetidamente.En mi último trabajo teníamos una función de desarrollo que también contaba las consultas por solicitud de página.Una gran cantidad de consultas para una rutina es el indicador más obvio de que su rutina no funciona bien con NHibernate.Si la cantidad de consultas por rutina o solicitud parece buena, probablemente deba ajustar la base de datos;asegurándose de tener suficiente memoria para almacenar planes de ejecución y datos en el caché, indexando correctamente sus datos, etc.

Un pequeño problema complicado con el que nos topamos fue con SetParameterList().La función le permite pasar fácilmente una lista de parámetros a una consulta.NHibernate implementó esto creando un parámetro para cada elemento pasado.Esto da como resultado un plan de consulta diferente para cada número de parámetros.Nuestros planes de ejecución casi siempre se liberaban del caché.Además, numerosos parámetros pueden ralentizar significativamente una consulta.Hicimos un truco personalizado de NHibernate para enviar los elementos como una lista delimitada en un solo parámetro.La lista estaba separada en SQL Server por una función de valor de tabla que nuestro truco insertó automáticamente en la cláusula IN de la consulta.Podría haber otras minas terrestres como esta dependiendo de su aplicación.SQL Profiler es la mejor manera de encontrarlos.

Otros consejos

SessionFactory de NHibernate es una operación costosa, por lo que una buena estrategia es crear un Singleton que garantice que solo haya UNA instancia de SessionFactory en la memoria:

   public class NHibernateSessionManager
    {
        private readonly ISessionFactory _sessionFactory;

        public static readonly NHibernateSessionManager Instance = new NHibernateSessionManager();

        private NHibernateSessionManager()
        {
            if (_sessionFactory == null)
            {
                System.Diagnostics.Debug.WriteLine("Factory was null - creating one");
                _sessionFactory = (new Configuration().Configure().BuildSessionFactory());
            }
        }

        public ISession GetSession()
        {
            return _sessionFactory.OpenSession();
        }

        public void Initialize()
        {
            ISession disposeMe = Instance.GetSession();
        }
    }

Luego, en su Global.Asax Application_Startup, puede inicializarlo:

protected void Application_Start()
{
    NHibernateSessionManager.Instance.Initialize();
}

Evitar y/o minimizar el Seleccione N + 1 problema al reconocer cuándo pasar de la carga diferida a la búsqueda ansiosa para consultas de rendimiento lento.

No es una recomendación, sino una herramienta para ayudarte:Profesor NH ( http://nhprof.com/ ) parece prometedor, puede evaluar su uso del marco ORM.Puede ser un buen punto de partida para ajustar NHibernate.

Sin detalles sobre los tipos de problemas de rendimiento que está viendo, sólo puedo ofrecer una generalización:En mi experiencia, la mayoría de los problemas de rendimiento de las consultas de bases de datos surgen de la falta de índices adecuados.Entonces, mi sugerencia para una primera acción sería verificar sus planes de consulta para consultas no indexadas.

NHibernate genera SQL bastante rápido desde el primer momento.Lo he estado usando durante un año y todavía tengo que escribir SQL simple con él.Todos mis problemas de rendimiento han sido de Normalización y falta de índices.

La solución más sencilla es examinar los planes de ejecución de sus consultas y crear índices adecuados, especialmente en sus columnas de clave externa.Si está utilizando Microsoft SQL Server, el "Asesor de optimización del motor de base de datos" le será de gran ayuda.

¿Solo "una recomendación por respuesta"?Entonces yo elegiría este:

Evite uniones duplicadas (también conocidas como productos cartesianos) debido a uniones a lo largo de dos o más asociaciones paralelas a muchos;utilice subconsultas Exists, MultiQueries o FetchMode "subselección" en su lugar.

Tomado de: Consejos para ajustar el rendimiento de Hibernación

¿Solo puedo limitar mi respuesta a una opción?En ese caso, seleccionaría que implemente el mecanismo de caché de segundo nivel de NHibernate.

De esta manera, para cada objeto en su archivo de mapeo podrá definir la estrategia de caché.La caché de segundo nivel mantendrá los objetos ya recuperados en la memoria y, por lo tanto, no realizará otro viaje de ida y vuelta a la base de datos.Este es un gran impulsor del rendimiento.

Su objetivo es definir los objetos a los que su aplicación accede constantemente.Entre ellos estarán los ajustes generales y similares.

Se puede encontrar mucha información sobre la caché de segundo nivel de nhibernate y cómo implementarla.

Buena suerte :)

Almacenamiento en caché, almacenamiento en caché, almacenamiento en caché: ¿está utilizando correctamente el almacenamiento en caché de primer nivel [cerrando sesiones prematuramente o utilizando StatelessSession para evitar el almacenamiento en caché de primer nivel]?¿Necesita configurar una caché de segundo nivel simple para valores que cambian con poca frecuencia?¿Puede almacenar en caché los conjuntos de resultados de consultas para acelerar las consultas que cambian con poca frecuencia?

[También configuración: ¿puedes configurar elementos como inmutables?¿Puede reestructurar las consultas para recuperar solo la información que necesita y transformarlas en la entidad original?¿Podrá Batman detener a Riddler antes de que llegue a la presa?...oh, lo siento, me dejé llevar.]

La elaboración de perfiles es el primer paso (incluso las pruebas unitarias cronometradas simples) para descubrir dónde se pueden obtener los mayores beneficios.

Para las colecciones, considere establecer el tamaño del lote para reducir la cantidad de declaraciones seleccionadas emitidas; consulte la sección Mejorando el desempeño para detalles

Si aún no estás usando la carga diferida (de manera apropiada), comienza.Obtener colecciones cuando no las necesitas es un desperdicio de todo.

Capítulo Mejorar el rendimiento describe esta y otras formas de mejorar el rendimiento.

Lo que dijo mucho tiempo libre.

Lea el Capítulo 19 de la documentación, "Mejora del rendimiento".
NHibernate: http://nhibernate.info/doc/nhibernate-reference/rendimiento.html
Hibernar: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html

Utilice SQL Profiler (o equivalente para la base de datos que esté utilizando) para localizar consultas de larga duración.Optimice esas consultas con índices apropiados.

Para llamadas a bases de datos utilizadas en casi todas las páginas de una aplicación, utilice CreateMultiQuery para devolver múltiples conjuntos de resultados de una única consulta de base de datos.

Y por supuesto, caché.La directiva OutputCache para páginas/controles.Almacenamiento en caché de NHibernate para datos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top