Sonntag, Mai 06, 2012

HASH JOIN Arbeitsweise

Bei der neuerlichen Lektüre des Kapitels 12 in Cost-Based Oracle von Jonathan Lewis wurde mir klar, dass es nicht schaden würde, einige der dort aufgeführten Punkte noch mal aufzuschreiben:
  • Bei der Durchführung eines HASH JOINs wird die INPUT-Menge mit Hilfe einer internen hashing Funktion in das Äquivalent eines in-memory single-table hash clusters konvertiert (sofern genügend Speicher zur Verfügung steht)
  • Anschließend werden die Daten der PROBE Menge gelesen und die hashing Funktion wird für jeden Satz auf die Join Spalte(n) angewendet, um zu prüfen, ob es einen entsprechenden Satz im in-memory hash cluster gibt.
  • Aufgrund der Verwendung der hashing Funktion kann ein HASH JOIN nur bei equality Bedingungen verwendet werden (und bei not exists), aber nicht bei range Bedingungen.
  • einschränkende Bedingungen auf eine der beiden Mengen können einen Index-Zugriff erlauben; die Join-Bedingung kann aber nicht zum indizierten Zugriff auf die PROBE Menge verwendet werden.
  • als INPUT wird die kleinere Menge verwendet, bestimmt über Anzahl Sätze * Satzlänge (= avg_col_len in user-tab_columns); wobei es Unterschiede zwischen der Statistik-Ermittlung mit dbms_stats und mit ANALYZE gibt (Stichwort: length byte).
  • da die Join-Bedingung nicht als Restriktion für die PROBE-Menge betrachtet wird, erfolgt häufig keine Partition Elimination im Fall einer partitionierten Tabelle (der CBO kann im Rahmen der Transformation allerdings eine pruning subquery ergänzen).
  • Wenn die INPUT Menge kleiner als die für die Session verfügbare hash_area_size ist (bzw. der über automatisches Speichermanagement zugewiesene Speicher), dann fällt der HASH JOIN in die Kategory OPTIMAL der workarea executions. Größere Mengen werden über ONEPASS oder MULTIPASS Operationen verarbeitet.
  • Die Prüfung der Join Matches erfolgt auf folgendem Weg
    • Beim Lesen der INPUT Menge baut Oracle ein Array von hash buckets im Arbeitsspeicher auf; um hash Kollisionen zu vermeiden, verwendet Oracle von vornherein relativ viel Speicher, um die Daten auf eine möglichst große Anzahl von Buckets verteilen zu können.
    • Die PROBE Menge wird (über den geeignetsten Mechanismus) gelesen und der für einen Satz passende Bucket ermittelt.
    • Wenn dieser Bucket leer ist, kann der Satz ignoriert werden. Ist er es nicht, so muss ein exakter Vergleich der Werte erfolgen, da die Möglichkeit der hash collision besteht. Ob ein bucket leer ist oder nicht, wird in einer bitmap Struktur erfasst.
  • Details zum HASH JOIN liefert Event 10104.
  • Der verfügbare Arbeitsspeicher (hash_area_size für manuelles Speichermanagement) wird in einzelne Partitionen aufgeteilt.
Die Details zu den ONEPASS- und MULTIPASS-Operationen liefere ich (wahrscheinlich) später nach.

Keine Kommentare:

Kommentar veröffentlichen