2010-02-01 12 views
5

Estoy usando NHibernate para ORM y he consolidado la carga de muchas entidades en una gran consulta.Latencia NHibernate es muy alta

De hecho estoy cargando un diccionario de palabras, alrededor de 500K entradas, y cada palabra se relaciona con otras. Ejecutar el proceso de carga en segundo plano puede ser muy complicado en nuestra aplicación, ya que tendríamos que cargar manualmente una entrada que no se ha cargado a tiempo, ya que cualquier palabra podría pedirse en cualquier momento. Nuestros únicos requisitos son que todos los datos se carguen lo más rápido posible. También probé usando una sesión sin estado, pero recibí una excepción de que las sesiones sin estado no pueden recuperar colecciones (por alguna razón, ¿tiene que ver con el hecho de que no hay caché para sesiones sin estado?)

El problema es que aunque la consulta no demora más de 25 segundos en SQLServer, toma mucho más de 3 minutos para ICriteria.List().

Usé NHProf para perfilar el proceso de carga y encontré que la creación de las entidades es una tarea costosa, que ocupa la mayor parte del tiempo de carga en NHibernate.

¿Hay algo que pueda hacer para reducir esta latencia? ¿Es costosa la asignación de memoria o es el "relleno" de los datos?

Gracias!

Respuesta

0

Perfilar el proceso de creación (por ejemplo, con el analizador de rendimiento VS) debería decirle exactamente cuál es la operación costosa. Si ya ha jugado con ajuste de carga diferido, entonces creo que la única solución buena es encapsular la lista devuelta para habilitar la paginación y devolver trozos más pequeños en algunas iteraciones. No estoy seguro de si NHibernate admite listas de resultados diferidos como JPA (es decir, no carga entidades del lector de datos hasta que sea necesario).

4

Quizás deba considerar el hecho de que NHibernate (como la mayoría de los ORM) no es especialmente adecuado (o previsto) para estos tipos de escenarios de carga masiva. ¿Cuántas filas está tratando de cargar, dar o tomar? ¿Que estás tratando de hacer? Pre-llenar un caché? ¿Se procesa por lotes?

Mi intuición es que debe considerar seriamente el propósito de su aplicación y elegir las tecnologías subyacentes en consecuencia. Tal vez pueda arrojar algo de luz sobre sus intenciones/requisitos?

EDITAR OK, a partir de sus comentarios Entiendo lo que está tratando de hacer aquí. Lo primero que haría sería crear un prototipo simple utilizando ADO.NET sin procesar para cargar los mismos datos, para tener una idea del mejor rendimiento posible mediante el acceso a datos estándar y colecciones en memoria. A continuación, revise con diferentes tipos de colección para ver qué funciona bien al poblar y buscar. Si cargar datos como este es demasiado lento, es hora de comenzar a buscar otros métodos de carga de datos: basado en archivos desde un archivo de datos local, hidratación de objetos pre-serializados, alguna forma de carga rápida bajo demanda, etc.

+0

¡Gracias por la respuesta rápida! Estoy tratando de cargar más de 500,000 filas, cada una de las cuales es una entidad. Cada entidad puede señalar hacia otras entidades. Estoy intentando completar esta lista lo más rápido posible con todas estas relaciones. No estoy escribiendo nada a la base de datos, pero después de experimentar con la carga lenta me di cuenta de que no se ajustaba a mis necesidades. Lo mejor que pude pensar es de alguna manera cargar los datos en un hilo diferente en algún tipo de patrón productor-consumidor, pero no tengo idea de cómo lo haces. ¿Algunas ideas? ¿Tiene algún consejo para otras tecnologías? Gracias! –

+1

Todavía no tengo ni idea de por qué querría cargar tantas entidades interrelacionadas. Eso hace que sea difícil encontrar sugerencias. Cargar los datos en segundo plano puede tener sentido, pero solo si su aplicación puede comenzar a hacer lo que sea necesario sin tener todos los datos en su lugar. En resumen, cuéntenos qué quiere lograr, cuáles son sus requisitos, tal vez podamos darle una sugerencia adecuada o dos. – tijmenvdk

+0

De hecho, estoy cargando un diccionario de palabras, cuando cada palabra se relaciona con otras. Lo de fondo podría ser muy complicado en nuestra aplicación, ya que tendríamos que cargar manualmente una entrada que no se haya cargado antes. El problema es que cualquiera de esas palabras podría pedirse en cualquier momento. Nuestros únicos requisitos son que todos los datos se carguen lo más rápido posible. También traté de usar una sesión sin estado, pero obtuve una excepción de que las sesiones sin estado no pueden obtener colecciones ... –

3

Cargando 500k entidades en una sesión de NHibernate no es una buena idea. La sesión está hecha para ser efímera y contener un número relativamente pequeño de entidades.

Si desea hacer este tipo de procesamiento por lotes en NHibernate, debe echar un vistazo a la sesión sin estado en lugar de la sesión ordinaria. Usar una sesión sin estado probablemente mejoraría drásticamente el rendimiento en este escenario. Sin embargo, al usar una sesión sin estado, usted pierde los beneficios de la memoria caché de primer nivel de NHibernate, como el seguimiento de cambios.

Se puede encontrar más información sobre StatelessSession en this article y in the NH docs en nhibernate.info.

En este caso, también recomendaría que considere utilizar ADO.NET directo en lugar de NHibernate. No estoy diciendo que deba cambiar su estrategia de acceso a datos completos a ADO.NET, pero es posible que desee considerar el uso de ADO.NET para las operaciones por lotes y el uso de NHibernate para los demás casos.

+0

Gracias. Intenté utilizar una sesión sin estado, pero obtuve el siguiente error: SessionException: "las colecciones no pueden ser recuperadas por una sesión sin estado". ¿Por qué debería ser así? ¿Hay alguna forma de eludir esto? –

+1

Si realmente necesita cargar las entidades con sus colecciones secundarias pobladas, entonces StatelessSession tampoco es una buena opción, ya que ignora las colecciones (según los documentos de NHForge). Probablemente, el motivo sea que StatelessSession se implementa a un nivel mucho más cercano a ADO.NET que la sesión ordinaria. Parece que ADO.NET sería una mejor opción que NHibernate en su escenario. –

Cuestiones relacionadas