Alle Abfragen von eXtreme Scale haben einen Abfrageplan. Der Plan beschreibt, wie die Abfragesteuerkomponente mit ObjectMaps und Indizes interagiert. Zeigen Sie den Abfrageplan an, um festzustellen, ob die Abfragezeichenfolge oder Indizes ordnungsgemäß verwendet werden. Der Abfrageplan kann auch verwendet werden, um die Unterschiede zu erkennen, die geringfügige Änderungen einer Abfragezeichenfolge in der Art und Weise, wie eXtreme Scale eine Abfrage ausführt, bewirken.
Der Abfrageplan kann auf die folgenden beiden Arten angezeigt werden:
Der Abfrageplan kann über einen ObjectGrid-Trace angezeigt werden. Zum Aktivieren des Trace für den Abfrageplan verwenden Sie die folgende Tracespezifikation:
QueryEnginePlan=debug=enabled
Einzelheiten zum Aktivieren des Trace und zum Auffinden der Traceprotokolldateien finden Sie im Abschnitt Trace erfassen.
Im Abfrageplan wird das Wort "for" verwendet, um anzuzeigen, dass die Abfrage durch eine ObjectMap-Sammlung oder durch eine abgeleitete Sammlung, wie z. B. q2.getEmps(), q2.dept oder eine temporäre Sammlung, die von einer inneren Schleife zurückgegeben wird, iteriert. Wenn die Sammlung aus einer ObjectMap stammt, zeigt der Abfrageplan an, ob eine sequenzielle Suche (angegeben mit INDEX SCAN), einen eindeutigen Index oder einen nicht eindeutigen Index verwendet wird. Der Abfrageplan verwendet eine Filterzeichenfolge, um die Bedingungsausdrücke aufzulisten, die auf eine Sammlung angewendet werden.
Ein kartesisches Produkt wird in der Objektabfrage gewöhnlich nicht verwendet. Die folgende Abfrage scannt die gesamte Map "EmpBean" in der äußeren Schleife und die gesamte Map "DeptBean" in der inneren Schleife:
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 )
Die folgende Abfrage ruft alle Mitarbeiternamen (employee) aus einer bestimmten Abteilung (department) ab, indem sie die Map "EmpBean" sequenziell durchsucht, um ein employee-Objekt abzurufen. Über das employee-Objekt navigiert die Abfrage zum zugehörigen department-Objekt und wendet den Filter "d.no=1" an. In diesem Beispiel hat jeder Mitarbeiter nur eine Referenz auf ein department-Objekt, so dass die innere Schleife nur ein einziges Mal ausgeführt wird:
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 )
Die folgende Abfrage entspricht der vorherigen Abfrage. Sie ist jedoch schneller, weil sie das Ergebnis über die Verwendung eines eindeutigen Index, der für die Primärschlüsselfeldnummer "DeptBean" auf ein einziges department-Objekt eingrenzt. Über das department-Objekt navigiert die Abfrage zu den zugehörigen employee-Objekten, um die Namen abzurufen:
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 )
Die folgende Abfrage sucht alle Mitarbeiter (employee), die für die Entwicklung (development) oder den Vertrieb (sales) arbeiten. Die Abfrage scannt die gesamte Map "EmpBean" und führt weitere Filterungen durch, indem Sie die Ausdrücke "d.name = 'Sales'" und "d.name='Dev'" auswertet:
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 )
Die folgende Abfrage entspricht der vorherigen Abfrage, führt aber einen anderen Abfrageplan aus und verwendet den über das Feld "name" erstellten Bereichsindex. Im Allgemeinen ist diese Abfrage schneller, weil der Index über das Feld "name" verwendet wird, um die department-Objekte einzugrenzen, was schnell ist, wenn es nur wenige Entwicklungs- oder Vertriebsabteilungen gibt.
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()
Die folgende Abfrage sucht Abteilungen, die keine Mitarbeiter haben:
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 )
Die folgende Abfrage entspricht der vorherigen Abfrage, verwendet aber die Skalarfunktion SIZE. Diese Abfrage hat eine ähnliche Leistung, ist aber einfacher zu schreiben:
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 )
Das folgende Beispiel zeigt eine weitere einfachere Methode, dieselbe Abfrage wie zuvor mit ähnlicher Leistung zu schreiben:
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 )
Die folgende Abfrage sucht alle Mitarbeiter mit einer Privatadresse, die mindestens einer der Adressen des Mitarbeiters entspricht, dessen Name mit dem Wert des Parameters übereinstimmt. Die innere Schleife ist nicht von der äußeren Schleife abhängig. Die Abfrage führt die innere Schleife ein einziges Mal aus:
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 )
Die folgende Abfrage entspricht der vorherigen Abfrage, hat aber eine Unterabfrage mit Korrelationsbezug. Außerdem wird die innere Schleife mehrfach ausgeführt:
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 )