tipos - Estrategia de búsqueda de Hibernate: cuándo usar "join" y cuándo usar "select"?
subconsultas hibernate (6)
JOIN es preferido, típicamente, por razones de rendimiento.
La única razón para usar SELECT es si está paginando resultados (estableciendo un desplazamiento y un límite) que tienen una relación muchos a muchos. Si usa JOIN, la entidad raíz aparecerá varias veces si contiene varios hijos muchos a muchos y esas "copias" cuentan contra su límite (incluso si Hibernate las colapsa después del hecho usando DISTINCT_ROOT_ENTITY).
La mayoría de las asociaciones de Hibernate admiten el parámetro "fetch":
fetch="join|select"
con "seleccionar" como valor predeterminado.
¿Cómo decidir cuál usar para qué asociación?
Traté de cambiar todo desde "seleccionar" hasta "unirme" a toda la aplicación: el número de consultas generadas disminuyó probablemente 10 veces, pero el rendimiento se mantuvo exactamente igual (incluso empeoró un poco).
Gracias.
Join se supone que resuelve el problema n + 1. Si tiene 10 padres, cada uno con 10 hijos, join requerirá una consulta y seleccionará requerirá 11 (uno para los padres y otro para los hijos de cada padre). Esto puede no ser un gran problema si la base de datos está en el mismo servidor que la aplicación o si la red es realmente rápida, pero si hay latencia en cada llamada a la base de datos, puede sumarse. El método de unión es un poco menos eficiente en la consulta inicial porque está duplicando las columnas principales en cada fila, pero solo realiza un viaje de ida y vuelta a la base de datos.
En general, si sé que voy a necesitar a los hijos de todos los padres, me uniré. Si solo voy a necesitar a los hijos de unos pocos padres, uso select.
La gente siempre habla sobre el rendimiento golpeado usando fetch = JOIN . Pero como reconozco, es importante que comprendamos la cantidad de registros de padres / hijos que estamos buscando:
Si desea obtener solo un registro principal único y esperando que no tenga muchos hijos, entonces le sugiero que use fetch = SELECT .
Si desea recuperar todos los registros principales, incluidos sus hijos, entonces sería mejor buscar fetch = JOIN
Solo para agregar una nota que, si los registros están buscando niños de forma perezosa ( lazy = true ), entonces no tendría ningún sentido usar fetch = JOIN ya que todos los registros padre e hijo se cargan en una sola toma.
Select obtendrá elementos secundarios al emitir una nueva consulta a la base de datos para ellos. Unir obtendrá objetos secundarios uniéndolos a la consulta principal. Es por eso que está viendo un rendimiento similar, incluso con un descenso en el número de consultas.
Seleccionar:
SELECT * FROM parent WHERE id=(whatever)
SELECT * FROM child WHERE id=(parent.child.id)
Unirse:
SELECT *
FROM parent
LEFT OUTER JOIN child ON parent.child.id=child.id
WHERE parent.id=(whatever)
En cuanto a cuándo usar uno sobre el otro ... No estoy seguro. Es probable que dependa del sistema de base de datos. Si uno siempre fue mejor que el otro, ¡dudo que se molesten en darle la opción! Si ve un rendimiento similar para cada uno, no me preocuparía.
Si el padre tiene muchos hijos y esos hijos a su vez tienen muchos otros, entonces en este caso la ''unión'' inicial podría ahogar la red. Mi sugerencia es usar ''seleccionar'' en este caso para dividir las selecciones.
fetching = "join" Si lo haces fetching = "join" recuperará toda la información en una sola instrucción de selección.
fetching = "select" si quiere paas la segunda instrucción select para recuperar la colección asociada que en ese caso usará fetch = "select".