Zusammengesetzte Pläne
Bei einem Join können Sie den Index angeben, der für den Abgleich verwendet werden soll.Sie müssen auch die JOIN
-Direktive für die beiden Streams im Plan verwenden:
select s.id, s.name, s.class, c.mentor
from students s
join classes c on c.name = s.class
plan join (s natural, c index (pk_classes));
Erweiterter Plan:
Select Expression -> Nested Loop Join (inner) -> Table "STUDENTS" as "S" Full Scan -> Filter -> Table "CLASSES" as "C" Access By ID -> Bitmap -> Index "PK_CLASSES" Unique Scan
Dieselbe Verknüpfung, sortiert nach einer indizierten Spalte:
select s.id, s.name, s.class, c.mentor
from students s
join classes c on c.name = s.class
plan join (s order pk_students, c index (pk_classes))
order by s.id;
Erweiterter Plan:
Select Expression -> Nested Loop Join (inner) -> Table "STUDENTS" as "S" Access By ID -> Index "PK_STUDENTS" Full Scan -> Filter -> Table "CLASSES" as "C" Access By ID -> Bitmap -> Index "PK_CLASSES" Unique Scan
Und für eine nicht indizierte Spalte:
select s.id, s.name, s.class, c.mentor
from students s
join classes c on c.name = s.class
plan sort (join (s natural, c index (pk_classes)))
order by s.name;
Erweiterter Plan:
Select Expression -> Sort (record length: 152, key length: 12) -> Nested Loop Join (inner) -> Table "STUDENTS" as "S" Full Scan -> Filter -> Table "CLASSES" as "C" Access By ID -> Bitmap -> Index "PK_CLASSES" Unique Scan
Mit einer hinzugefügten Suchbedingung:
select s.id, s.name, s.class, c.mentor
from students s
join classes c on c.name = s.class
where s.class <= '2'
plan sort (join (s index (fk_student_class), c index (pk_classes)))
order by s.name;
Erweiterter Plan:
Select Expression -> Sort (record length: 152, key length: 12) -> Nested Loop Join (inner) -> Filter -> Table "STUDENTS" as "S" Access By ID -> Bitmap -> Index "FK_STUDENT_CLASS" Range Scan (lower bound: 1/1) -> Filter -> Table "CLASSES" as "C" Access By ID -> Bitmap -> Index "PK_CLASSES" Unique Scan
Als Left Outer Join:
select s.id, s.name, s.class, c.mentor
from classes c
left join students s on c.name = s.class
where s.class <= '2'
plan sort (join (c natural, s index (fk_student_class)))
order by s.name;
Erweiterter Plan:
Select Expression -> Sort (record length: 192, key length: 56) -> Filter -> Nested Loop Join (outer) -> Table "CLASSES" as "C" Full Scan -> Filter -> Table "STUDENTS" as "S" Access By ID -> Bitmap -> Index "FK_STUDENT_CLASS" Range Scan (full match)
Wenn keine Indizes verfügbar sind, die der Join-Bedingung entsprechen (oder wenn Sie sie nicht verwenden möchten), können Sie die Streams mit der Methode HASH
oder MERGE
verbinden.
Um eine Verbindung mit der HASH
-Methode im Plan herzustellen, wird die HASH
-Direktive anstelle der JOIN
-Direktive verwendet.In diesem Fall wird der kleinere (sekundäre) Strom vollständig in einem internen Puffer materialisiert.Beim Lesen dieses sekundären Streams wird eine Hash-Funktion angewendet und ein Paar {Hash, Zeiger auf Puffer} in eine Hash-Tabelle geschrieben.Dann wird der primäre Stream gelesen und sein Hash-Schlüssel wird gegen die Hash-Tabelle getestet.
select *
from students s
join classes c on c.cookie = s.cookie
plan hash (c natural, s natural)
Erweiterter Plan:
Select Expression -> Filter -> Hash Join (inner) -> Table "STUDENTS" as "S" Full Scan -> Record Buffer (record length: 145) -> Table "CLASSES" as "C" Full Scan
Für einen 'MERGE'-Join muss der Plan zuerst beide Streams in deren Join-Spalte(n) sortieren und dann zusammenführen.Dies wird mit der SORT
-Direktive (die wir bereits gesehen haben) und MERGE
statt JOIN
erreicht:
select * from students s
join classes c on c.cookie = s.cookie
plan merge (sort (c natural), sort (s natural));
Das Hinzufügen einer ORDER BY
-Klausel bedeutet, dass das Ergebnis der Zusammenführung ebenfalls sortiert werden muss:
select * from students s
join classes c on c.cookie = s.cookie
plan sort (merge (sort (c natural), sort (s natural)))
order by c.name, s.id;
Schließlich fügen wir eine Suchbedingung für zwei indizierbare Spalten der Tabelle STUDENTS
hinzu:
select * from students s
join classes c on c.cookie = s.cookie
where s.id < 10 and s.class <= '2'
plan sort (merge (sort (c natural),
sort (s index (pk_students, fk_student_class))))
order by c.name, s.id;
Wie aus der formalen Syntaxdefinition hervorgeht, können JOIN
s und MERGE
s im Plan mehr als zwei Streams kombinieren.Außerdem kann jeder Planausdruck als Planelement in einem umfassenden Plan verwendet werden.Dies bedeutet, dass Pläne bestimmter komplizierter Abfragen verschiedene Verschachtelungsebenen haben können.
Schließlich können Sie statt MERGE
auch SORT MERGE
schreiben.Da dies absolut keinen Unterschied macht und zu Verwirrung mit “real” SORT
-Direktiven führen kann (die einen Unterschied machen), ist es wahrscheinlich am besten, beim einfachen MERGE
zu bleiben.
Neben dem Plan für die Hauptabfrage können Sie für jede Unterabfrage einen Plan angeben.Die folgende Abfrage mit mehreren Plänen funktioniert beispielsweise:
select *
from color
where exists (
select *
from hors
where horse.code_color = color.code_color
plan (horse index (fk_horse_color)))
plan (color natural)
Warning
|
Gelegentlich akzeptiert der Optimierer einen Plan und folgt ihm dann nicht, obwohl er ihn nicht als ungültig zurückweist.Ein solches Beispiel war
Es ist ratsam, einen solchen Plan als “veraltet” zu behandeln. |