.net - name - ¿Cuál es la mejor manera de mejorar el rendimiento de NHibernate?
meta name keywords (12)
Sin ninguna especificación sobre 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 bases de datos surgen de la falta de índices adecuados. Así que mi sugerencia para una primera acción sería verificar sus planes de consulta para consultas no indexadas.
Tengo una aplicación que utiliza NHibernate como su ORM y, a veces, tiene problemas de rendimiento debido a la forma en que se accede a los datos. ¿Qué tipo de cosas se pueden hacer para mejorar el rendimiento de NHibernate? (Por favor, limite a una recomendación por respuesta)
NHibernate genera SQL bastante rápido nada más sacarlo de la caja. Lo he usado durante un año, y aún tengo que escribir SQL desnudo 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 ajuste de motor de base de datos" ayuda mucho con esto.
¿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 usted puede definir la estrategia de caché. La memoria caché de segundo nivel mantendrá los objetos ya recuperados en la memoria y, por lo tanto, no realizará otra ida y vuelta a la base de datos. Este es un gran refuerzo de rendimiento.
Tu objetivo es definir los objetos a los que accede constantemente tu aplicación. Entre ellos habrá ajustes generales y similares.
Hay mucha información para encontrar el caché de segundo nivel nhibernate y cómo implementarlo.
Buena suerte :)
El primer y más dramático problema de rendimiento 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 sesión para cada ejecución de la aplicación y esa fábrica debe crear todas las sesiones.
En ese sentido, debe 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 sola sesión por solicitud. Si descarta su sesión con frecuencia, no está obteniendo los beneficios de su caché. El uso inteligente de la memoria caché de la 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 es perezoso cargar sus referencias de objeto. Si no lo está, se podrían cargar gráficos completos de objetos incluso para las consultas más simples. Solo hay ciertas razones para no hacerlo, 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 contrario de la carga perezosa. Mientras recorre las jerarquías de objetos o recorre las colecciones, puede ser fácil perder el registro de la cantidad de consultas que realiza y termina con un número exponencial de consultas. La obtención con ganas se puede hacer por consulta con un FETCH JOIN. En circunstancias excepcionales, como si hay un par de tablas en particular que siempre busca unirse, considere desactivar la carga diferida para esa relación.
Como siempre, SQL Profiler es una gran manera de encontrar consultas que se ejecutan lentamente o se realizan de forma repetida. En mi último trabajo, teníamos una función de desarrollo que contabilizaba consultas por solicitud de página también. Una gran cantidad 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 no tenga que ajustar la base de datos; asegurándose de tener suficiente memoria para almacenar los planes de ejecución y los datos en la memoria caché, indexando correctamente sus datos, etc.
Un pequeño y complicado problema con el que nos encontramos fue con SetParameterList (). La función le permite pasar fácilmente una lista de parámetros a una consulta. NHibernate lo implementó al crear 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 fueron liberados 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 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.
Almacenamiento en caché, almacenamiento en caché, almacenamiento en caché: ¿Está utilizando correctamente el almacenamiento en caché de primer nivel [cierre prematuro de sesiones o uso de StatelessSession para eludir el almacenamiento en caché de primer nivel]? ¿Necesita configurar un caché de segundo nivel simple para valores que cambian con poca frecuencia? ¿Puede guardar en caché los conjuntos de resultados de las consultas para acelerar las consultas que cambian con poca frecuencia?
[También configuración: ¿puede configurar elementos como inmutables? ¿Puede reestructurar consultas para recuperar solo la información que necesita y transformarla en la entidad original? ¿Podrá Batman detener al Acertijo antes de llegar a la presa? ... oh, lo siento se dejó llevar.]
NHibernate''s SessionFactory 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();
}
Evite y / o minimice el problema de Select N + 1 al reconocer cuándo pasar de la carga diferida a la búsqueda ansiosa para las consultas de ejecución lenta.
No es una recomendación, sino una herramienta para ayudarlo: NH Prof ( http://nhprof.com/ ) parece ser prometedor, puede evaluar su uso del marco ORM. Puede ser un buen punto de partida para su ajuste de NHibernate.
"Una recomendación por respuesta" solamente? Entonces yo iría por este:
Evite combinar duplicados (también productos cartesianos) debido a las uniones a lo largo de dos o más asociaciones paralelas a muchas; utilice Exists-subqueries, MultiQueries o FetchMode "subselect" en su lugar.
Tomado de: sugerencias de ajuste de rendimiento de Hibernate
Lo que lotsoffreetime dijo.
Lea el Capítulo 19 de la documentación, "Mejora del rendimiento".
NHibernate: http://nhibernate.info/doc/nhibernate-reference/performance.html
Hibernate: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html
Utilice el Analizador de SQL (o equivalente para la base de datos que está utilizando) para localizar consultas de larga ejecución. Optimice esas consultas con los índices apropiados.
Para las llamadas a la base de datos utilizadas en casi todas las páginas de una aplicación, use CreateMultiQuery para devolver múltiples resultados desde 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.
La creación de perfiles es el primer paso, incluso simples pruebas de unidad cronometradas, para descubrir dónde se pueden obtener los mayores beneficios.
Para las colecciones, considere establecer el tamaño del lote para reducir el número de declaraciones seleccionadas emitidas; consulte la sección Mejora del rendimiento para obtener más información.
Si aún no está utilizando la carga diferida (apropiadamente), comience. Obtener 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.