¿Cuál es la mejor manera de mejorar el rendimiento de NHibernate?


Tengo una aplicación que usa NHibernate como su OR y a veces experimenta problemas de rendimiento debido a cómo se accede a los datos por ella. ¿Qué tipo de cosas se pueden hacer para mejorar el rendimiento de NHibernate? (Se ruega limitar a una recomendación por respuesta)

Author: Ray Vega, 2008-09-16

12 answers

El primer y más dramático problema de rendimiento que puede encontrar 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 sesión para cada ejecución de la aplicación y todas las sesiones deben ser creadas por esa fábrica.

En esa línea, debe continuar usando la misma sesión siempre y cuando tenga sentido. Esto variará según la aplicación, pero para la mayoría de las aplicaciones web, una sola sesión por solicitud es recomendar. Si desperdicia su sesión con frecuencia, no está obteniendo los beneficios de su caché. El uso inteligente de la 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 desea asegurarse de que está cargando perezosamente sus referencias de objetos. Si no lo está, se podrían cargar gráficos de objetos completos incluso para las consultas más simples. Solo hay ciertas razones para no hacer esto, pero siempre es mejor comenzar con la carga lenta y volver a cambiar según sea necesario.

Eso nos lleva a la búsqueda ansiosa, lo contrario de la carga perezosa. Al recorrer jerarquías de objetos o recorrer colecciones, puede ser fácil perder la pista de cuántas consultas está realizando y terminar con un número exponencial de consultas. La búsqueda ansiosa se puede hacer por consulta con una COMBINACIÓN de BÚSQUEDA. En raras circunstancias, como si hay un par de tablas en particular, siempre busca unirse, considera desactivar la carga perezosa para esa relación.

Como siempre, SQL Profiler es una excelente manera de encontrar consultas que se ejecutan lentamente o se realizan repetidamente. En mi último trabajo teníamos una función de desarrollo que contaba las consultas por solicitud de página también. Un alto número de consultas para una rutina es el indicador más obvio de que su rutina no está funcionando bien con NHibernate. Si el número de consultas por rutina o solicitud se ve bien, probablemente se haya reducido a afinar la base de datos; seguro que tienes suficiente memoria para almacenar planes de ejecución y datos en la caché, indexar correctamente tus datos, etc.

Un pequeño problema complicado que encontramos 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é. También, numerosos parámetros pueden ralentizar significativamente una consulta. Hicimos un hack personalizado de NHibernate para enviar los elementos como una lista delimitada en un solo parámetro. La lista fue separada en SQL Server por una función de valor de tabla que nuestro hack 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.

 51
Author: Chuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-24 17:16:20

La SessionFactory de NHibernate es una operación costosa, por lo que una buena estrategia es crear un Singleton que asegure que solo haya una instancia de SessionFactory en 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();
        }
    }

Entonces en su Global.Asax Application_Startup, puede inicializarlo:

protected void Application_Start()
{
    NHibernateSessionManager.Instance.Initialize();
}
 25
Author: David P,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-26 23:27:29

Evite y/o minimice el problema Select N + 1 reconociendo cuándo cambiar de carga lenta a búsqueda ansiosa para consultas de rendimiento lento.

 11
Author: Ray Vega,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-02 20:03:11

No hay una recomendación, pero una herramienta para ayudarle: NH Prof ( http://nhprof.com / ) parece prometedor, puede evaluar su uso del marco framework. Puede ser un buen punto de partida para su afinación de NHibernate.

 10
Author: MatthieuGD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-02-02 19:00:44

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

 4
Author: Mike Monette,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-15 21:40:33

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 desnudo con él. Todos mis problemas de rendimiento han sido de Normalización y la falta de índices.

La solución más fácil es examinar los planes de ejecución de sus consultas y crear índices adecuados, especialmente en sus columnas de clave foránea. Si está utilizando Microsoft SQL Server, el "Asesor de Ajuste del Motor de base de datos" ayuda mucho con esto.

 3
Author: Eric Lathrop,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-19 01:02:45

¿Solo"una recomendación por respuesta"? Entonces me gustaría ir por este:

Evite los duplicados de unión (TAMBIÉN conocidos como productos cartesianos) debido a uniones a lo largo de dos o más asociaciones paralelas a-many; use Exists-subqueries, MultiQueries o FetchMode "subselect" en su lugar.

Tomado de: Hibernate Performance Tuning Tips

 3
Author: gnome26,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-11-07 20:34:16

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

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

Su objetivo es definir los objetos a los que se accede constantemente su solicitud. 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:)

 1
Author: Hace,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-09-23 21:24:28

Caching, Caching, Caching? ¿Está usando su caché de primer nivel correctamente [cerrando sesiones prematuramente, o usando StatelessSession para omitir el caché de primer nivel]? ¿Necesita configurar una caché simple de segundo nivel 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? ¿puede establecer elementos como inmutables? ¿Puede reestructurar las consultas para recuperar solo la información que necesita y transformarlas en la entidad original? ¿Batman será capaz de detener al Acertijo antes de que llegue a la presa? ... lo siento, me dejé llevar.]

 1
Author: Watson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-09 14:58:53

El perfilado es el primer paso - incluso simples pruebas unitarias cronometradas - para averiguar dónde se pueden obtener las mayores ganancias

Para las colecciones, considere establecer el tamaño del lote para reducir el número de declaraciones select emitidas; consulte la sección Mejora del rendimiento para obtener más detalles

 1
Author: Richard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-12 10:41:36

Si aún no está utilizando la carga lenta (apropiadamente), comience. Buscar colecciones cuando no las necesitas es un desperdicio de todo.

El capítulo Mejora del rendimiento describe esta y otras formas de mejorar el rendimiento.

 1
Author: lotsoffreetime,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-12 10:45:08

Lo que lotsoffreetime dijo.

Lea el Capítulo 19 de la documentación, "Mejorar el rendimiento".
NHibernate: http://nhibernate.info/doc/nhibernate-reference/performance.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 los índices adecuados.

Para las llamadas a la base de datos casi todas las páginas de una aplicación, use Createmultizery para devolver varios conjuntos de resultados de una sola consulta de base de datos.

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

 0
Author: Axl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-11 16:12:21