Abfrageplan

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:

Methode getPlan

Die Methode getPlan in den Schnittstellen ObjectQuery und Query gibt eine Zeichenfolge zurück, die den Abfrageplan beschreibt. Diese Zeichenfolge kann in der Standardausgabe oder in einem Protokoll angezeigt werden.
Anmerkung: In einer verteilten Umgebung wird die Methode getPlan nicht für den Server ausgeführt und gibt keine definierten Indizes zurück. Zum Anzeigen des Plans auf dem Server verwenden Sie einen Agenten.

Trace für Abfrageplan

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.

Beispiele für Abfragepläne

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  )