2012-04-25 10 views
14

Estoy escribiendo una aplicación web usando Hibernate 3.Hibernate Performance Best Practice?

Entonces, después de un tiempo noté que algo iba lento. Así que probé el generador de perfiles de hibernación y descubrí que hibernate hará innecesariamente muchas llamadas a bases de datos para una operación simple. La razón es, por supuesto, que cargo un Objeto (este objeto tiene varios "padres") y estos "padres" tienen otros "padres". Así que, hibernación básica, los carga a todos, aunque solo necesito el objeto básico. Ok, entonces miré la carga lenta. Lo que me llevó a la excepción Lazyloading, porque tengo una aplicación web MVC.

Así que ahora estoy un poco confundido en cuanto a cuál es mi mejor enfoque para esto. Básicamente, todo lo que necesito es actualizar un solo campo en un objeto. Ya tengo la clave de objeto.

Debería I: 1. Indague en Lazy-loading. ¿Y luego reescribo mi aplicación para una vista de sesión abierta? 2. Adéntrate en la carga diferida. Y luego reescribo mi día para ser más específico. P.ej. escribiendo métodos DAO que devolverán objetos instanciados solo con lo que es necesario para cada caso de uso? Podría ser una gran cantidad de métodos adicionales ... 3. Scratch hibernate y hacerlo yo mismo? 4. No puedo pensar en otras soluciones ahora mismo. ¿Alguna sugerencia?

¿Cuál es la mejor práctica?

Respuesta

25
  • No utilice combinaciones a menos que realmente lo necesite. No le permitirán usar ni la carga lenta, ni usar el caché de segundo nivel para las asociaciones
  • Use lazy = "extra" para colecciones grandes, no recuperará todos los elementos hasta que lo solicite, también puede usar el tamaño() método, por ejemplo, sin obtener elementos de DB
  • Utilice el método load() si es posible, ya que no emite una consulta de selección hasta que sea necesario. P.ej. si usted tiene un libro y un autor y que desea asociar entre sí, esto no emitirá ningún selecciona, sólo el único inserto:

    Book b = (Book) session.load(Book.class, bookId); 
    Author a = (Author) session.load(Author.class, authorId); 
    b.setAuthor(a); 
    session.save(b); 
    
  • Use llamado consultas (en sus archivos o HBM en @NamedQuery) para que no se analicen durante cada consulta.No utilice la API Criteria hasta que sea necesario (que hace imposible el uso de caché PreparedStatement en este caso)

  • Uso OSIV en su aplicación web, ya que cargará los datos sólo cuando/si es necesario
  • Utilice los modos de sólo lectura para solo seleccionar: session.setReadOnly(object, true). Esto hará que Hibernate no guarde una instantánea original de la entidad seleccionada en el contexto persistente para más verificaciones sucias.
  • Caché de segundo nivel de usuario y Query Cache para leer en su mayoría y datos de solo lectura.
  • Utilice FlushMode.COMMIT en lugar de AUTO para que Hibernate no emita la selección antes de las actualizaciones, pero esté listo para que esto pueda dar lugar a que se escriban datos obsoletos (aunque Optimistic Locking puede ayudarlo).
  • Eche un vistazo a la obtención de lotes (tamaño de lote) para seleccionar varias entidades/colecciones a la vez en lugar de emitir consultas separadas para cada una.
  • Realiza consultas como 'seleccionar nueva entidad (id, someField) desde Entity' para recuperar solo los campos obligatorios. Eche un vistazo a los transformadores de resultados.
  • Usar operaciones por lotes (como eliminar) si es necesario
  • Si utiliza consultas nativas, especifique explícitamente qué regiones de caché deben invalidarse (de forma predeterminada, todas).
  • Eche un vistazo a la ruta materializada y conjuntos anidados para estructuras similares a árboles.
  • Establezca c3p0.max_statements para habilitar la memoria caché PreparedStatment en la agrupación y habilite la memoria caché de sentencias de su base de datos si está desactivada de forma predeterminada.
  • Uso StatelessSession si es posible, que supera los cheques sucios, en cascada, interceptores, etc.
  • No utilice la paginación (setMaxResults(), setFirstResult()), junto con las consultas que contienen une a las colecciones, esto se traducirá en todos los registros extraídos de la base de datos y la paginación pasarán en la memoria de Hibernate. Si quieres paginación, idealmente no deberías usar uniones. Si no puede escapar, de nuevo, use la búsqueda por lotes.

En realidad hay muchos trucos, pero no recuerdo más por el momento.

+0

OSIV puede explicar no he tenido –

1

Creo que desea opinar section in the Hibernate manual.

Espero que su problema original de "... irrazonablemente muchas llamadas a bases de datos ..." es una instancia de lo que ellos llaman el "problema N + 1 selecciona". Si es así, tienen opciones sobre cómo lidiar con eso.

  1. Crear el tipo de búsqueda Unirse. Luego tendrá una única selección con varias combinaciones, suponiendo que no haya colecciones intermedias.
  2. Do lazy loading.
  3. Probablemente algunos otros, por ejemplo FetchProfiles con los que no tengo experiencia.

Los dos primeros se pueden especificar en el nivel de asociación, y el tipo de búsqueda se puede anular en el nivel de consulta. Debería poder hacer que su consulta haga solo lo que necesita, no más, y hacerlo con una 'buena' consulta SQL con estas herramientas.

3

Como he explicado en mi this article o High-Performance JavaPersistence book, hay muchas cosas que puede hacer para acelerar el rendimiento de hibernación, como:

  1. Enabling SQL statement logging para que pueda validar todas las declaraciones e incluso detect N+1 query problems during testing.
  2. gestión de la conexión de base de datos y el seguimiento utilizando FlexyPool
  3. JDBC batching para reducir el número de idas y vueltas necesarias para presentar INSERT, UPDATE y DELETE.
  4. JDBC Statement caching
  5. optimizadores de identificador de APP como pooled or pooled-lo
  6. La elección de los tipos de columnas compactas
  7. Use las relaciones correctas: bidirectional @OneToMany instead of unidirectional one, utilizando @MapsId for @OneToOne, using Set for @ManyToMany
  8. Uso inheritance the right way y preferring SINGLE_TABLE for performance reasons
  9. Minding the Persistence Context size and avoiding long-running transactions
  10. utilizar la caché de sistema operativo , DB caché antes de saltar a caché de segundo nivel que h también es útil para sacar datos del nodo primario al hacer la replicación de bases de datos
  11. capacidades de consulta de base de datos rienda suelta a través de SQL native queries
  12. de Split escribe entre múltiples uno-a-uno entidades a reduce optimistic locking false positives y obtener una mejor oportunidad de golpear la caché de base de datos, incluso al modificar ciertas entidades.
Cuestiones relacionadas