web-dev-qa-db-fra.com

Stratégie de récupération Hibernate - quand utiliser "join" et quand utiliser "select"?

La plupart des associations Hibernate prennent en charge le paramètre "fetch":

fetch="join|select"

"select" étant la valeur par défaut.

Comment décider lequel utiliser pour quelle association?

J'ai essayé de tout changer de "sélectionner" à "rejoindre" une large gamme d'applications - le nombre de requêtes générées a probablement diminué 10 fois, mais les performances sont restées exactement les mêmes (elles sont même devenues un peu moins bonnes).

Merci.

47
serg

Join est censé résoudre le problème n + 1. Si vous avez 10 parents, chacun avec 10 enfants, rejoindre demandera une requête et sélectionnez en exigera 11 (un pour les parents et un pour les enfants de chaque parent). Cela peut ne pas être un gros problème si la base de données se trouve sur le même serveur que l'application ou si le réseau est vraiment rapide, mais s'il y a une latence dans chaque appel de base de données, cela peut s'additionner. La méthode de jointure est un peu moins efficace sur la requête initiale car vous dupliquez les colonnes parentes dans chaque ligne, mais vous ne faites qu'un aller-retour vers la base de données.

Généralement, si je sais que je vais avoir besoin des enfants de tous les parents, j'y vais avec join. Si je n'ai besoin que des enfants de quelques parents, j'utilise select.

41
Brian Deterling

Sélectionnez récupérera les éléments enfants en émettant une nouvelle requête pour eux dans la base de données. Join récupère les éléments enfants en les joignant à la requête du parent. C'est pourquoi vous voyez des performances similaires, même avec une baisse du nombre de requêtes.

Sélectionner:

SELECT * FROM parent WHERE id=(whatever)
SELECT * FROM child WHERE id=(parent.child.id)

Joindre:

SELECT *
FROM parent
LEFT OUTER JOIN child ON parent.child.id=child.id
WHERE parent.id=(whatever)

Quant à savoir quand utiliser l'un sur l'autre ... Pas tout à fait sûr. Cela dépend probablement du système de base de données. Si l'un était toujours meilleur que l'autre, je doute qu'ils se donneraient la peine de vous donner l'option! Si vous voyez des performances similaires pour chacun, je ne m'en inquiéterais pas.

9
jdmichal

Si le parent a beaucoup d'enfants et que ces enfants ont à leur tour beaucoup d'autres, alors dans ce cas, la "jointure" initiale peut étouffer le réseau. Ma suggestion est d'utiliser "sélectionner" dans ce cas pour diviser les sélections.

2
MullaBihari

JOIN est préférable, généralement, pour des raisons de performances.

La seule raison d'utiliser SELECT est si vous recherchez des résultats (définissant un décalage et une limite) qui ont une relation plusieurs-à-plusieurs. Si vous utilisez JOIN, l'entité racine apparaîtra plusieurs fois si elle contient plusieurs enfants plusieurs à plusieurs et que ces "copies" comptent pour votre limite (même si Hibernate les réduit après coup en utilisant DISTINCT_ROOT_ENTITY).

1
Daedalus

fetching = "join" Si vous effectuez fetching = "join" il récupérera toutes les informations dans une seule instruction select.

fetching = "select" si vous voulez paas la deuxième instruction select pour récupérer la collection associée que dans ce cas vous utiliserez fetch = "select".

source: Hibernate Fetching Strategies

1
user528050

Les gens parlent toujours des performances atteintes en utilisant fetch = JOIN. Mais comme je le pense, il est important pour nous de comprendre le nombre d'enregistrements parent/enfant que nous recherchons:

Si vous ne souhaitez récupérer qu'un seul enregistrement Parent et que vous vous attendez à ce qu'il n'ait pas beaucoup d'enfants, je vous suggère d'utiliser fetch = SELECT.

Si vous souhaitez récupérer tous les enregistrements parents, y compris ses enfants, il serait préférable de choisir fetch = JOIN

Juste pour ajouter une note que, si les enregistrements récupèrent paresseusement des enfants (paresseux = vrai), cela n'aurait aucun sens d'utiliser fetch = JOIN puisque tous les les dossiers des parents et des enfants sont chargés en une seule fois.

0
Jagadeesh