Toutes les requêtes eXtreme Scale ont un plan de requête. Le plan décrit la manière dont le moteur de requête interagit avec les ObjectMaps et les index. L'affichage du plan de requête permet de déterminer si la chaîne de requête ou les index sont utilisés de manière appropriée. Le plan de requête peut également servir à explorer les conséquences de légères modifications dans une chaîne de recherche sur l'exécution d'une requête par eXtreme Scale.
Le plan de requête peut être affiché de deux manières :
Le plan de requête peut être affiché à l'aide de la trace d'ObjectGrid. Pour activer la trace des plans de requête, utilisez les spécifications de trace suivantes :
QueryEnginePlan=debug=enabled
Voir Collecte de trace pour savoir comment activer la trace et repérer les fichiers de trace.
Le plan de requête utilise le mot (word) for pour indiquer que la requête opère une itération dans une collection ObjectMap ou, dans une collection dérivée par exemple : q2.getEmps(), q2.dept, ou dans une collection temporaire retournée par une boucle interne. Si la collection provient d'un ObjectMap, le plan de requête indique si un index unique ou non unique d'analyse séquentielle (signalé par INDEX SCAN) est utilisée. Le plan de requête utilise une chaîne de filtrage pour afficher la liste des expressions de condition appliquées à une collection.
Un produit cartésien est rarement utilisé dans la requête d'objet. La requête qui suit analyse la totalité de la mappe EmpBean dans la boucle externe et elle analyse la totalité de la mappe DeptBean dans la boucle interne :
SELECT e, d FROM EmpBean e, DeptBean d
Plan trace:
for q2 in EmpBean ObjectMap using INDEX SCAN
for q3 in DeptBean ObjectMap using INDEX SCAN
returning new Tuple( q2, q3 )
La requête qui suit extrait tous les noms de salariés d'un département particulier en analysant de manière séquentielle la mappe EmpBean à la recherche d'un objet employee. A partir de cet objet employee, la requête navigue vers l'objet department de l'objet employee et elle applique le filtre d.no=1. Dans cet exemple, chaque employé n'a qu'une seule référence à l'objet department, et la boucle interne ne s'exécute donc qu'une seule fois :
SELECT e.name FROM EmpBean e JOIN e.dept d WHERE d.no=1
Plan trace:
for q2 in EmpBean ObjectMap using INDEX SCAN
for q3 in q2.dept
filter ( q3.getNo() = 1 )
returning new Tuple( q2.name )
La requête qui suit équivaut à la requête précédente. Cependant, la requête suivante est plus performant car elle commence par restreindre le résultat à un seul objet department en utilisant l'index unique qui est défini sur le numéro de zone de clé primaire DeptBean. A partir de cet objet department, la requête navigue vers les objets employee de l'objet department pour obtenir leurs noms :
SELECT e.name FROM DeptBean d JOIN d.emps e WHERE d.no=1
Plan trace:
for q2 in DeptBean ObjectMap using UNIQUE INDEX key=(1)
for q3 in q2.getEmps()
returning new Tuple( q3.name )
La requête suivant recherche tous les salariés qui travaillent pour le développement ou pour les ventes. La requête analyse la totalité de la mappe EmpBean et procède à un filtrage supplémentaire en évaluant les expressions d.name = 'Sales' ou d.name='Dev'
SELECT e FROM EmpBean e, in (e.dept) d WHERE d.name = 'Sales'
or d.name='Dev'
Plan trace:
for q2 in EmpBean ObjectMap using INDEX SCAN
for q3 in q2.dept
filter (( q3.getName() = Sales ) OR ( q3.getName() = Dev ) )
returning new Tuple( q2 )
La requête qui suit équivaut à l'exemple précédent, mais elle exécute un autre plan de requête en utilisant l'index de plages construit sur la zone name. En général, cette requête offre de meilleures performances car l'index sur la zone name est utilisée pour restreindre les objets department, avec à la clé une exécution rapide si seuls quelques départements sont du développement ou des ventes.
SELECT e FROM DeptBean d, in(d.emps) e WHERE d.name='Dev' or d.name='Sales'
Plan trace:
IteratorUnionIndex of
for q2 in DeptBean ObjectMap using INDEX on name = (Dev)
for q3 in q2.getEmps()
for q2 in DeptBean ObjectMap using INDEX on name = (Sales)
for q3 in q2.getEmps()
La requête qui suit recherche les départements qui n'ont pas de salariés :
SELECT d FROM DeptBean d WHERE NOT EXISTS(select e from d.emps e)
Plan trace:
for q2 in DeptBean ObjectMap using INDEX SCAN
filter ( NOT EXISTS ( correlated collection defined as
for q3 in q2.getEmps()
returning new Tuple( q3 )
returning new Tuple( q2 )
La requête qui suit équivaut à la requête précédente, mais elle utilise la fonction scalaire SIZE. Cette requête offre des performances similaires, mais elle est plus facile à écrire.
SELECT d FROM DeptBean d WHERE SIZE(d.emps)=0
for q2 in DeptBean ObjectMap using INDEX SCAN
filter (SIZE( q2.getEmps()) = 0 )
returning new Tuple( q2 )
L'exemple qui suit est une autre manière d'écrire la même requête avec des performances similaires, mais, elle aussi, elle est plus facile à écrire.
SELECT d FROM DeptBean d WHERE d.emps is EMPTY
Plan trace:
for q2 in DeptBean ObjectMap using INDEX SCAN
filter ( q2.getEmps() IS EMPTY )
returning new Tuple( q2 )
La requête qui suit recherche tous les salariés dont le domicile correspond à l'une au moins des adresses du salarié dont le nom égale la valeur du paramètre. La boucle interne n'a aucune dépendance à l'égard de la boucle externe. La requête exécute la boucle interne une seule fois.
SELECT e FROM EmpBean e WHERE e.home = any (SELECT e1.home FROM EmpBean e1
WHERE e1.name=?1)
for q2 in EmpBean ObjectMap using INDEX SCAN
filter ( q2.home =ANY temp collection defined as
for q3 in EmpBean ObjectMap using INDEX on name = ( ?1)
returning new Tuple( q3.home )
)
returning new Tuple( q2 )
La requête qui suit équivaut à la requête précédente, mais elle comporte une sous-requête corrélée. Par ailleurs, la boucle interne s'exécute de manière répétitive.
SELECT e FROM EmpBean e WHERE EXISTS(SELECT e1 FROM EmpBean e1 WHERE
e.home=e1.home and e1.name=?1)
Plan trace:
for q2 in EmpBean ObjectMap using INDEX SCAN
filter ( EXISTS ( correlated collection defined as
for q3 in EmpBean ObjectMap using INDEX on name = (?1)
filter ( q2.home = q3.home )
returning new Tuple( q3 )
returning new Tuple( q2 )