2009-11-23 23 views
9

Recientemente tuve un fenómeno bastante extraño. Tuve que obtener un recuento que incluye uniones en varias tablas con diferentes condiciones WHERE. Implementé la consulta primero con los criterios API de hibernación. Creó correctamente la instrucción SQL preparada solicitada, pero fue bastante lenta. Re-implementé entonces toda la consulta usando HQL. Fue bastante desagradable hacerlo, pero el resultado fue mucho más rápido que con la API de Criteria. ¿Alguien sabe el motivo de ese comportamiento? Supuse que Criteria y HQL Framework usan la misma base de código para transformarlo a SQL.Hibernate Query vs Criteria Performance

Ésta es la consulta:

select count(*) from R r where r.ISREPLACEDBY = 0 
and r.STATUS='OK' and r.A = ? 
and r.C in 
    (select distinct RC from CX cx where cx.FROMDATE >= ? and cx.FROMDATE <=?) 
+0

¿Puede mostrar las consultas HQL y criterios? –

+0

La consulta depende de los parámetros. Una de las más simples es statetments como la siguiente: select count (*) de R r, donde r.ISREPLACEDBY = 0 y r.STATUS = 'OK' y R. A =? R. C y en (seleccione RC distinta de CX cx donde cx.FROMDATE> =? y cx.FROMDATE <=?) – bertolami

Respuesta

17

Supongo que finalmente encontré el motivo. Parece que el criterio api crea nuevos nombres de variables cada vez que se ejecuta una declaración preparada. La base de datos (en nuestro caso, DB2) calcula un nuevo plan de ejecución de consulta cada vez que se ejecuta la instrucción. Por otro lado, HQL usa los mismos nombres de variable, lo que permite que la base de datos reutilice los planes de ejecución de consultas.

0

por lo general creen que HQL está muy cerca óptima, ya que es casi recta SQL con algunas sustituciones. Supongo que la traducción de HQL a SQL es solo una sustitución; la API Criteria probablemente genera HQL para luego transformarse. En general, HQL es tu mejor apuesta.

+2

En realidad, los criterios se traduce directamente en SQL. p.ej. Criterion.toSqlString – qualidafial

+0

Eso no es verdad. Primero genera HQL que luego se analiza. – mnp

0

Criterios de Hibernate utilizar la reflexión para generar statments SQL

+0

Otro problema con los criterios de la API es que genera el HQL cada vez (bueno, ya que podría ser diferente cada vez). Este HQL también se traduce a SQL todo el tiempo. Esta traducción intenta cargar algunos de los tokens a través del cargador de clases (por ejemplo, generatedBla0) que arroja una ClassNotFoundException. Esta operación es bastante caro ya que pasa por todos los cargadores de clases antes de que el último puede generar una excepción y también implica algunos bloqueos en el cargador de clases que afecta greately rendimiento. Se olvidó de mencionar que debido a un error, los enteros podrían insertarse en el SQL en lugar de los parámetros. – mnp

3

criterios, en teoría debería tener menos sobrecarga que una consulta HQL (a excepción de consultas con nombre, que voy a llegar a). Esto se debe a que Criteria no necesita analizar nada. Las consultas HQL se analizan con un analizador basado en ANTLR y luego el AST resultante se convierte en SQL. Sin embargo, con HQL/JPAQL puede definir consultas con nombre, donde el SQL se genera cuando se inicia SessionFactory. En teoría, las consultas con nombre tienen menos sobrecarga que Criteria. Por lo tanto, en términos de gastos generales de SQL generación tenemos:

  1. Named HQL/JPAQL consultas - la generación de SQL sucede sólo una vez.
  2. Criterios: no es necesario analizar antes de generar.
  3. (sin nombre) HQL/JPAQL Query - Parse, luego generar. Dicho esto, la elección de una técnica de consulta basada en la sobrecarga del análisis sintáctico y la generación de SQL es probablemente un error en mi opinión. Esta sobrecarga suele ser muy pequeña en comparación con la realización de una consulta real en un servidor de base de datos real con datos reales. Si esta sobrecarga realmente aparece al crear el perfil de la aplicación, entonces tal vez debería cambiar a una consulta con nombre.

Estas son las cosas que considerar al decidir entre Criteria y HQL/JPAQL:

  • En primer lugar, usted tiene que decidir si estás bien con tener una dependencia de la API de Hibernate propietaria en su código. JPA no tiene Criteria.
  • criterios es muy bueno en el manejo de muchos parámetros de búsqueda opcional tal como se puede encontrar en una página web típica con un multi-parámetro 'búsqueda' . Con HQL, los desarrolladores tienden a virar en la cláusula expresiones con StringBuilder (¡evitar esto!). Con Criteria, usted no necesita hacer eso.
  • HQL/JPAQL se puede utilizar para la mayoría de otras cosas, porque el código tiende a ser más pequeño y más fácil para los desarrolladores a entender.
  • consultas frecuentes Realmente se pueden convertir en consultas con nombre si se utiliza HQL. Prefiero hacer esto más tarde, después de algunos perfiles.

Usted puede leer algo de información adicional aquí http://tech.puredanger.com/2009/07/10/hibernate-query-cache/

Cuestiones relacionadas