12.8. Réglage de la performance
12.8.1. Algorithmes de chargement de lots alternatifs
Hibernate permet de charger les données d'associations à l'aide de l'une des quatre stratégies de récupération : joindre (join), sélectionnez (select), sous-sélectionner (subselect) et par lots (batch). En dehors de ces quatre stratégies, le chargement par lots permet des plus grands gains de performance car c'est une stratégie d'optimisation pour l'extraction sélective. Dans cette stratégie, Hibernate récupère un lot d'instances d'entités ou de collections dans une instruction SELECT unique en spécifiant une liste de clés primaires ou étrangères. L'extraction de lot est une optimisation de la stratégie de récupération sélective différée.
Il existe deux manières de configurer l'extraction par batch: Niveau Par classe ou Niveau Par collection.
- Niveau Par classeLors du chargement de données sur un niveau par classe, Hibernate, requiert la taille de lot de l'association à pré-charger lorsqu'il est interrogé. Par exemple, imaginons que lors de l'exécution, vous ayez 30 instances d'un objet
voiture
chargées dans la session. Chaque objetvoiture
appartient à un objetpropriétaire
. Si vous deviez parcourir tous les objetsvoiture
et appeler leurs propriétaires, par un chargementdifféré
(lazy loading), Hibernate émettra 30 instructions select - une pour chaque propriétaire. Il s'agit d'un goulot d'étranglement de performance.À la place, vous pouvez dire à Hibernate de charger à l'avance le prochain lot de propriétaires avant qu'ils aient été interrogés par une requête. Quand un objetowner
(propriétaire) est interrogé, Hibernate interrogera ces objets à plusieurs reprises dans le même énoncé SELECT.Le nombre d'objetsowner
(propriétaire) à interroger à l'avance dépend du paramètrebatch-size
spécifié en cours de configuration :<class name="owner" batch-size="10"></class>
Cela indique à Hibernate d'interroger au moins 10 objetsowner
au cas où ils seraient nécessaires dans un avenir proche. Lorsqu'un utilisateur interroge le propriétaireowner
decar A
, le propriétaireowner
decar B
peut déjà avoir été chargé dans un lot de chargement. Lorsque l'utilisateur a besoin du propriétaireowner
decar B
, au lieu d'aller à la base de données (et émettre une instruction SELECT), la valeur peut être récupérée de la session en cours.En plus du paramètrebatch-size
, Hibernate 4.2.0 a introduit un nouvel élément de configuration pour améliorer la performance de chargement de lots. La configuration s'appelleBatch Fetch Style
et est spécifiée par le paramètrehibernate.batch_fetch_style
.Il existe trois styles d'extraction de lots pris en charge : LEGACY, PADDED et DYNAMIC. Pour spécifier le style, utiliserorg.hibernate.cfg.AvailableSettings#BATCH_FETCH_STYLE
.- LEGACY : dans le style hérité de chargement, une série de tailles de lots pré-construits basées
ArrayHelper.getBatchSizes(int)
sont utilisées. Les lots sont chargés à l'aide de la taille de lot de pré-construction suivante à partir du nombre d'identificateurs existants pouvant être mis en lot.En continuant avec l'exemple suivant, ayant une taillebatch-size
de 30, les tailles de lot pré-construits sont [30, 15, 10, 9, 8, 7, .., 1]. Si l'on tente de mettre en lots 29 identifiants, on obtiendra des lots de 15, 10 et 4. Il y aura 3 requêtes SQL correspondantes, chacune chargeant 15, 10 et 4 propriétaires de la base de données. - PADDED - similaire au style de chargement de classes LEGACY. Utilise toujours des tailles de lots pré-construits, mais utilise la taille de lot supérieure et remplit les espaces réservés de l'identifiant supplémentaire.Tout comme dans l'exemple ci-dessus, si 30 objets propriétaires doivent être initialisés, il ne pourra y avoir qu'une demande exécutée dans la base de données.Cependant, si 29 objets propriétaires doivent être initialisés, Hibernate n'exécutera qu'un seul énoncé select SQL de taille de lot 30, avec l'espace supplémentaire rempli par un identifiant répété.
- Dynamic - bien que toujours conforme à la limitation de la taille des lots, ce style de chargement dynamique de lots construit son énoncé SQL SELECT à l'aide du nombre réel d'objets à charger.Par exemple, pour 30 objets propriétaires, et une taille de lot maximale de 30, un appel pour récupérer 30 objets propriétaires entraînera une instruction SQL SELECT. Un appel pour récupérer 35 se traduira en deux énoncés SQL, ayant pour taille de lot 30 et 5, respectivement. Hibernate modifiera dynamiquement le second énoncé SQL pour maintenir à 5, le nombre requis, tout en restant sous la restriction de 30 pour la taille des lots. C'est différent de la version PADDED, car le deuxième SQL ne sera pas PADDED et à la différence du style LEGACY, il n'y a pas de taille fixe pour le second énoncé SQL - le second SQL est créé dynamiquement.Pour une requête inférieure à 30 identifiants, ce style ne chargera de façon dynamique que le nombre d'identifiants requis.
- Niveau Par collectionHibernate peut aussi mettre en lots des collections de chargement, en respectant la taille ou les styles des lots d'extraction suivant la liste de la section par-classe ci-dessus.Pour inverser l'exemple utilisé dans la section précédente, considérons que vous deviez charger tous les objets
car
(voiture) appartenant à chaque objetowner
(propriétaire). Si 10 objets propriétaireowner
sont chargés dans la session en cours, itérer tous les propriétaires va générer 10 énoncés SELECT, un pour chaque appel de méthode àgetCars()
. Si vous activez l'extraction de lot pour la collection de voitures dans le mappage du propriétaire, Hibernate pourra chercher ces collections à l'avance, comme illustré ci-dessous.<class name="Owner"><set name="cars" batch-size="5"></set></class>
Donc, avec une taille de lot égale à 5 et en utilisant le style de lot hérité pour charger 10 collections, Hibernate exécutera deux énoncés SELECT, récupérant chacun 5 collections.