
Envoyé par
Oelth
je cherche à récupérer un certain nombre
de ces document_element pour en effectuer un count sur une page d'accueil (j'affiche des choses du genre : 'éléments en attente : 25', 'éléments validés:14', etc.).
Mais chaque requête met environ 10 secondes à se réaliser, donc autant dire que cette page d'accueil prend presque une minute pour s'afficher, ce qui n'est pas normal pour des requêtes aussi simples.
Autrement dit, au lieu de demander à la DB de faire le count, tu demande à JPA de rapatrier toutes les données pour ensuite faire l'affichage de list.size(). Pas bien!
Il y a une différence à faire un truc du genre
1 2 3 4 5 6 7 8 9
| List<Document> docs = em.createQuery("from Document d where d.owner=:owner").setParamenter("owner","tartempion").getResultList();
boolean valid = 0;
for (Document d : docs) {
for (Element e:docs.getElements()){
if (e.isValidated()){
valid++;
}
}
} |
et faire
Number n = (Number)em.createQuery("select count(e) from Document d inner join d.elements e where d.owner=:owner and e.validated = true").setParamenter("owner","tartempion").getUniqueResult();
Au début j'ai pensé à revoir mon code, factoriser certaines parties histoire d'éviter de taper sur la base à plusieurs reprises pour la même opération. Mais même en faisant cela, je n'ai pas vu de changement significatif.
Après j'ai tenté d'optimiser mes requêtes, rebelotte, aucune différence (remplacer les associations faites automatiquement par jpa, par des inner join ou autres).
Avant d'optimiser, as-tu profilé tes requêtes pour savoir ce qui se passe. Il y a deux chose qui peuvent t'aider à comprendre où tu perds du temps:
activer le debug dans ton driver sql: permettra de voir toutes les requetes avec paramètres faites à la DB => C'est dépendant du driver
activer dans ton implémentation jpa l'affichage des requêtes, exemple avec le show sql de hibernate => Ca te permettra de voir comment ton entitymanager interprète tes requêtes.
Vu que ta requête va vite en mode sql, je pense pas que l'optimsiation de stable ne soit en cause.
Aussi question con: est-ce que tu n'aurais pas désactivé le lazy-loading dans tes relation one to many?
J'ai alors supposé que jpa chargeait le contenu de chaque entité en entier (quelques centaines de milliers d'entrées) puis faisait les traitements dans son contexte de persistance (corrigez moi si je me trompe

).
JPA charge ce que tu lui demande, pas plus. Mais une entité n'est jamais chargée à moitié. Par contre le nombre d'entité chargée est dépendant de ta requête JPQL. Si tu lui demande tout, il va tout prendre. Ta clause where doit être correcte. On n'ira pas plus loin si tu ne fournis pas de code.
JE travaille sans cache de second niveau, et je n'ai aucun soucis. Quand au cache de premier niveau, je pense même pas qu'il soit désactivable, tellement il est nécessaire au fonctionnement de JPA. Comme il est associé à la transaction en cours, aucun problème de concurrence dedans.
Partager