Stratégie de récupération Hibernate - quand utiliser «rejoindre» et quand utiliser «sélectionner»?

StackOverflow https://stackoverflow.com/questions/617145

  •  03-07-2019
  •  | 
  •  

Question

La plupart des associations Hibernate sont favorables à "fetch". paramètre:

fetch="join|select"

avec "sélectionner" étant la valeur par défaut.

Comment décider lequel utiliser pour quelle association?

J'ai essayé de tout modifier à partir de & select; select " rejoindre " application large - le nombre de requêtes générées a probablement diminué de 10 fois, mais les performances sont restées identiques (voire même empiré).

Merci.

Était-ce utile?

La solution

La jointure est supposée résoudre le problème n + 1. Si vous avez 10 parents, chacun avec 10 enfants, la jointure nécessitera une requête et la requête sélectionnée 11 (une pour les parents et une pour les enfants de chaque parent). Ce n'est peut-être pas si grave si la base de données se trouve sur le même serveur que l'application ou si le réseau est très rapide, mais s'il y a du temps de latence dans chaque appel de base de données, tout peut s'accumuler. La méthode de jointure est un peu moins efficace sur la requête initiale car vous dupliquez les colonnes parent dans chaque ligne, mais vous ne faites qu'un aller-retour vers la base de données.

En général, si je sais que je vais avoir besoin des enfants de tous les parents, je vais avec nous. Si je n'ai besoin que des enfants de quelques parents, j'utilise select.

Autres conseils

Select récupérera les éléments enfants en envoyant une nouvelle requête à la base de données les concernant. Join récupérera les éléments enfants en les joignant à la requête du parent. C’est pourquoi vos performances sont similaires, même avec une baisse du nombre de requêtes.

Sélectionnez:

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

Rejoindre:

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 la possibilité! Si vous constatez des performances similaires pour chacun, je ne m'en inquiéterais pas.

Si le parent a beaucoup d'enfants et que ceux-ci en ont beaucoup d'autres, dans ce cas, la "jointure" initiale peut étrangler le réseau. Ma suggestion est d'utiliser "sélectionner" dans ce cas pour diviser les sélections.

fetching = " rejoindre " Si vous récupérez = & "rejoindre" " il recopiera toutes les informations dans une seule instruction select.

recherche si vous souhaitez utiliser la deuxième instruction select pour extraire la collection associée, utilisez fetch = "select".

source: Stratégies de récupération avancée par Hibernate

JOIN est préférable pour des raisons de performances.

Une des raisons d'utiliser SELECT est si vous paginez (définissez un décalage et une limite) les résultats qui ont une relation plusieurs à plusieurs. Si vous utilisez JOIN, l’entité racine apparaîtra plusieurs fois si elle contient plusieurs enfants multiples et que ces "copies" sont des "copies". comptez contre votre limite (même si Hibernate les réduit ensuite en utilisant DISTINCT_ROOT_ENTITY).

Les utilisateurs discutent toujours de leurs performances en utilisant fetch = JOIN . Mais, à mon avis, il est important pour nous de comprendre le nombre d’enregistrements parent / enfant que nous récupérons:

Si vous souhaitez extraire un seul enregistrement parent et espérez qu'il ne compte pas beaucoup d'enfants, je vous suggère d'utiliser fetch = SELECT .

Si vous souhaitez extraire tous les enregistrements parents, y compris ses enfants, il vaut mieux choisir fetch = JOIN

.

Juste pour ajouter une note indiquant que, si les enregistrements récupéraient paresseusement des enfants ( lazy = true ), cela n'aurait aucun sens d'utiliser fetch = JOIN , car tous les enregistrements parents et enfants sont chargés en un seul coup.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top