-
- Downloads
Improve tree browsing request #68
-
Cette première optimisation permet de réduire drastiquement le temps d'une requête de forage de l'arbre (récupérer les enfants d'un noeud). Quelques tests :
- Chargement de la page d'accueil de l'espace DRIIHM : 3.53s -> 1.18s
- Requête pour charger les enfants de "Les ressources de la communauté" : 213ms -> 53ms
- Requête pour charger les enfants du géocatalogue de l'OHM BMP : 4.51s -> 90ms
-
Pour la distribution je m'en suis occupé 2895cadc (c'était les 4
OPTIONAL
qui ralentissait). Pour les autres ressources il faut que je regarde.La suppression du contexte virtuoso est utile pour les cas de collision de contexte que l'on a eu mais ne semble pas avoir d'impact sur le temps d'exécution.
Ce qui a simplifié la requête ici est le fait d'utiliser
UNION
pour séparer les deux parties de cette requête. Je pense que du coup Virtuoso arrive a "paralléliser" la récupération des deux parties de cetteUNION
.De ce que j'ai lu/vu les points qui ralentissent nos requêtes sont essentiellement
- les
OPTIONAL
(qui agissent comme des LEFT JOIN) - les filtres sur l'identifiant (il serait plus efficace de spécifier le triplet directement mais vu qu'on a des typages différents (non typé, rdfs:Literal, xsd:string, ...) on est contraint de passer par un
FILTER
)
- les
-
Exactement et c'est pourquoi je ne les ai pas simplement enlevés mais remplacés en formulant la requête différemment quand c'était possible.
Dans certains cas on peut remplacer des
OPTIONAL
par desUNION
sans changer le sens et le résultat de la requête.Exemple, la requête suivante :
CONSTRUCT { <resourcesURI> dct:identifier ?id. <resourcesURI> dct:title ?title. <resourcesURI> dct:description ?description. } WHERE { <resourcesURI> dct:identifier ?id. OPTIONAL { <resourcesURI> dct:title ?title. } OPTIONAL { <resourcesURI> dct:description ?description. } }
et sa version sans
OPTIONAL
:CONSTRUCT { <resourcesURI> dct:identifier ?id. <resourcesURI> dct:title ?title. <resourcesURI> dct:description ?description. } WHERE { <resourcesURI> dct:identifier ?id. { <resourcesURI> dct:title ?title. } UNION { <resourcesURI> dct:description ?description. } }
Documentation sur la question : https://www.snee.com/bobdc.blog/2014/10/dropping-optional-blocks-from.html
-
PS : Sur mon dernier exemple on pourrait aussi l'écrire de la sorte vu le comportement de
VALUES
CONSTRUCT { <resourcesURI> dct:identifier ?id. <resourcesURI> ?p ?o. } WHERE { <resourcesURI> dct:identifier ?id. VALUES ?p { dct:title dct:description } <resourcesURI> ?p ?o. }
-
Effectivement. Il est possible en allant sur l'éditeur de requête de générer le rapport de compilation de la requête SPARQL pour comprendre.
Il me semble qu'un CONSTRUCT est plus long qu'un SELECT. A-t-on vraiment besoin d'un CONTRUCT pour l'arbre? Ne peut-on pas faire un SELECT pour naviguer le graphe et un CONSTRUCT pour afficher un descripteur?
Il est toujours possible de faire du préchargement anticipé.
Aussi, il y aura du tuning du serveur à faire.
-
Personnellement je trouve ce rapport de compilation assez compliqué à analyser pour améliorer les requêtes et je n'ai pas le temps de l'investiguer plus.
En effet le
CONSTRUCT
est plus long que leSELECT
sauf que leCONSTRUCT
permet de récupérer un graphe (et donc un arbre selon la requête effectuée) et permet grâce à la sortie au format JSON-LD différentes manipulations (compactage et framing) facilitant le traitement de la donnée. Il serait possible possible d'utiliser leSELECT
à la place duCONSTRUCT
pour la requête de forage en profondeur de l'arbre mais cela demanderait des adaptations et donc du temps (ce que je n'ai pas en ce moment).