Mittwoch, Oktober 29, 2014

first_rows und first_rows_n

Jonathan Lewis weist in seinem Blog darauf hin, dass die Optimizer-Modi first_rows und first_rows_n deutlich weniger gemein haben, als man vielleicht annehmen könnte. Während first_rows seit langem nur noch aus Gründen der Abwärtskompatibiltät unterstützt wird und diverse Heuristiken benutzt, um die Optionen des Optimizers einzuschränken, arbeiten die first_rows_n-Varianten strikt kostenbasiert, ohne dem Optimizer massiv in die Arbeit zu pfuschen. Tatsächlich gibt es allerdings einen Fall, in dem first_rows_n sich so verhält wie first_rows, nämlich die - durchaus merkwürdige - Variante first_rows(0). In diesem Fall wechselt der Optimizer intern tatsächlich auf die Strategie first_rows. Allerdings gibt der Herr Lewis zu Recht zu bedenken: "Mind you, if you only want the first zero rows of the result set there’s a much better trick you can use to optimise the query – don’t run the query."

Für mich persönlich brachte der Artikel noch mal die Erinnerung, dass der Session-Parameter und der Hint first_rows_n eine leicht abweichende Parametrisierung besitzen (die auch explizit dokumentiert ist): während der Parameter nur die Werte 1, 10, 100 und 1000 als gültig betrachtet, kann man im Hint für n jeden beliebigen ganzzahligen Wert angeben. Nachlesen kann man die Details in meinen Kommentaren zum Artikeln und der erläuternden (man könnte auch sagen: richtig stellenden) Antwort des Autors.

Der Vollständigkeit halber hier noch ein Link auf meinen älteren Versuch, dem Costing für first_rows_n auf die Spur zu kommen, zum dem mir damals Randolf Geist die Pointe geliefert hatte (man könnte auch sagen: die Richtigstellung).

Montag, Oktober 27, 2014

Temp Table Transformation

Randolf Geist erläutert in seinem Blog das Verhalten der Temp Table Transformation, die hauptsächlich (aber nicht ausschließlich) dann anzutreffen ist, wenn eine CTE im Plan mehrfach referenziert wird und mindestens ein (Filter- oder Join-) Prädikat enthält, und weist insbesondere darauf hin, dass diese Transformation nicht kostenbasiert erfolgt, sondern automatisch. In Fällen, in denen eine zusätzliche Bedingung jenseits des CTE-Kontexts eine dramatische Reduzierung der Ergebnismenge hervorrufen würde, ist diese Materialisierung demnach ausgesprochen kontraproduktiv. Darüber hinaus rufen die materialiserten CTEs in solchen Fällen seit 11.2.0.4 offenbar extrem abwegige Cardinality-Schätzungen hervor, die in komplexeren Plänen sehr unglückliche Konsequenzen hervorrufen könnten. Insgesamt scheint es gute Gründe zu geben, die Materialisierung von CTEs sehr genau zu beobachten und ggf. durch den (nach wie vor undokumentierten) Inline-Hint zu vermeiden.

Sonntag, Oktober 26, 2014

Histogramme, Cardinality und der Optimizer Mode first_rows_100

Eine interessante Antwort auf die Frage nach unplausiblen Cardinalities, die sich trotz frequency histogram ergeben, hat Jonathan Lewis in einem OTN-Forums-Thread gegeben. Der vom Fragesteller gelieferte handliche Testfall zeigte sehr deutlich, dass in seinem System mit 11.2.0.4 für einfache Queries sehr merkwürde Cardinalities ermittelt wurden, obwohl das vorhandene Histogramm die tatsächliche Verteilung exakt abbildete. Diverse Beiträger konnten nur feststellen, dass das Verhalten in ihren Systemen (zwischen 11.2.0.1 und 12.1.0.2) nicht reproduzierbar war, aber der Herr Lewis konnte das fehlende Puzzle-Teil benennen: wenn man den Optimizer-Mode auf first_rows_100 umstellt, werden aus den plausiblen Schätzungen augenblicklich recht nutzlose Zahlen. Ich pflege die Wirkung der first_rows_n-Einstellungen regelmäßig zu unterschätzen und sollte mir endlich merken, wie invasiv dieser Modus tatsächlich ist.

Dienstag, Oktober 21, 2014

Index Reorganisation

Franck Pachot beantwortet in seinem Blog eine Frage, die mir gelegentlich durch den Kopf gegangen ist, ohne dass ich mich ernsthaft um ihre Beantwortung gekümmert hätte: welche Form der Reorganisation eines Index ist unter welchen Voraussetzungen die passendste? Dazu liefert er einen einfachen Testfall, zu dem er die relevanten Statistiken zum Index und zur Ressourcen-Nutzung im Rahmen der Reorganisation beisteuert. Die Ergebnisse lauten ungefähr:
  • COALESCE: eine Online-Operation, die die leaf blocks defragmentiert, aber nicht wieder frei gibt, sondern für die zukünftige Verwendung in der Index-Struktur hält.
  • SHRINK SPACE COMPACT: ebenfalls eine Online-Operation, die ungefähr das gleiche leistet wie coalesce, aber etwas mehr LIOs hervorruft und die leaf Blocks etwas effektiver aufräumt (Status: FS4 statt FS2).
  • SHRINK SPACE: wieder eine Online-Operation mit nahezu identischer Ressourcen-Nutzung wie das shrink space compact, aber in diesem Fall werden die geräumten Blocks tatsächlich wieder freigegeben.
  • REBUILD: erfordert ein share lock, das konkurrierende DML-Operationen blockiert, benötigt aber weniger Ressourcen und führt zu einer vollständig aufgeräumten Index-Struktur: in diesem Fall wird auch die Index-Höhe auf den passenden Wert zurückgeführt - was im Fall des kompletten Neuaufbaus keine besondere Überraschung darstellt.
  • REBUILD ONLINE: ein EE-Feature, das - wie der Name vermuten lässt - den Neuaufbau ohne umfangreicheres Locking ermöglicht (in der Regel auf Kosten erhöhter Ressourcen-Nutzung.
Insbesondere die Tatsache, dass das shrink space mehr leistet als das shrink space compact ist ein Aspekt, der mir schon mehrfach entfallen ist..

Montag, Oktober 20, 2014

Advanced Index Compression in 12c

Leider schaffe ich es derzeit nicht, mir eigene Gedanken zu machen, so dass ich mich darauf beschränken muss, anderer Leute Ergebnisse zu reproduzieren. Einer der Autoren, bei denen ich das recht gerne mache, ist Richard Foote, der inzwischen wieder sehr regelmäßig neue Artikel schreibt. Zwei davon betreffen die in 12c eingeführte Advanced Index Compression:
  • Index Compression Part V: 12c Advanced Index Compression (Little Wonder): erläutert die Hintergünde dieser neuen Option (die eigens lizenziert werden muss). Bisher war es bei der klassischen Index--Komprimierung, bei der Duplikate in den führenden Spalten eines Index durch Referenzen auf eine Prefix-Sektion im Block ersetzt werden, ohne Weiteres möglich, den Index durch die Komprimierung zu vergrößern - dann nämlich, wenn es zu wenig Wiederholungen gab, um den Overhead der eingeführten Symboltabelle zu rechtfertigen. Bei der Advanced Index Compression wird dieses Problem auf zwei Ebenen behandelt: zum einen automatisiert die Option die Bestimmung eines sinnvollen Komprimierungsgrads, zum anderen wählt sie die Komprimierung blockspezifisch aus, so dass einzelne Bereiche des Index, die sich gut komprimieren lassen, besser gepackt werden als andere Bereiche mit wenigen Duplikaten.
  • Index Compression Part VI: 12c Index Advanced Compression Block Dumps (Tumble and Twirl): beschäftigt sich mit den technischen Details der Implementierung und mit der Repräsentation der Komprimierung im Block-Dump. Der zentrale Punkt sind die Einträge kdxlepnro (nro = number of rows?) und kdxlepnco (nco = number of columns?) im Index-Block-Dump, von denen der erste die Anzahl der Einträge in der Prefix-Tabelle angibt und der zweite die Anzahl komprimierter Spalten. Bei kdxlepnco taucht zusätzlich in Klammern die Angabe (Adaptive) auf, die auf die Verwendung des neuen Features hinweist.
Weitere Artikel sind angekündigt, die ich dann voraussichtlich ebenfalls hier zusammenfasse werde. Grundsätzlich sieht das wie eine sehr sinnvolle Funktionalität aus - ich hatte mich in der Vergangenheit häufiger gefragt, wieso ich zunächst einen plausiblen Kompressionsgrad ermitteln musste (per ANALYZE INDEX), ehe ich diesem Vorschlag folgte, da ich an dieser Stelle recht wenig Spielraum für individuelle Anpassungen und vom Vorschlag abweichende Entscheidungen sah.