Plan de requête

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 :

Méthode getPlan

La méthode getPlan sur les interfaces ObjectQuery et Requête les interfaces renvoie une chaîne qui décrit le plan de requête. Cette chaîne peut être affichée de manière standard ou dans un journal.
Remarque : Dans un environnement réparti, la méthode getPlan ne s'exécute pas sur le serveur et elle ne reflète aucun index défini. Pour afficher le plan, utilisez un agent pour visualiser le plan sur le serveur.

Trace du plan de requête

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.

Exemples de plans de requête

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  )