Dienstag, Juni 28, 2016

Index Sanity Check für Cardinality Schätzungen

Auf das Thema weise ich in den OTN-Foren recht häufig hin und da ist es gut, dass Jonathan Lewis einen Artikel dazu geschrieben hat, auf den man verweisen kann: die Löschung eines Index kann den Ausführungsplan einer Query auch dann ändern, wenn der Index gar nicht im Execution Plan erscheint. Die Erklärung dafür sind Sanity Checks die auf der Basis der Index-Statistiken für mehrspaltige Indizes operieren. Im Artikel stellt Jonathan Lewis ein kleines Beispiel vor, das diesen Sachverhalt deutlich macht: darin wird ein Index gelöscht, der im Ausführungsplan keine Rolle spielt. Dieser Index ist auf einer Kombination von drei Spalten angelegt, von denen die erste 10 distinkte Werte enthält, die zweite nur einen und die dritte wiederum 20 distinkte Werte. Die Kombination der Selektivitäten würde - da der Oracle Optimizer bekanntlich von unabhängigen Wahrscheinlichkeiten ausgeht, also keine Abhängigkeiten annimmt - daraus 10 * 1 * 20 = 200 machen. In den Index-Statistiken ist aber festgehalten, dass die Zahl der tatsächlich auftretenden Kombinationen nur bei 20 liegt und dieser Wert wird dann auch vom Optimizer berücksichtigt. Die Löschung des Index führt dann natürlich zum Verlust der Information und zu einer weniger akkuraten Schätzung. Seit 11g kann man in einem solchen Fall den Informationsverlust durch Anlage von Extended Statistics auf der Spaltengruppe vermeiden, aber grundsätzlich zeigt das Beispiel, dass man beim Löschen "unbenutzter" Indizes vorsichtig sein sollte.

Montag, Juni 20, 2016

Typ-Konvertierung und cardinality-Schätzung

Jonathan Lewis weit in seinem Scratchpad darauf hin, dass Funktionsaufrufe für Spalten im Fall einer Bedingung "function(column) = constant" üblicherweise zu einer Schätzung von 1% führen. Dies gilt aber nicht für einfache Typ-Umwandlungen: eine Bedingung in der eine Charakter-Spalte mit einem numerischen Wert verglichen wird, verwendet eine Variante der Standardformel zur Berechnung gleichverteilter Werte, nämlich (Anzahl Werte)/(Anzahl distinkter Werte) - wobei die Klassifizierung als Variante damit zusammenhängt, dass die Anzahl distinkter Werte in einer Charakter-Spalte nicht zwingend der Anzahl der in ihr repräsentierter numerischer Werte entspricht, da 9 als '9' und '09' und beliebig viele andere Strings dargestellt werden kann. Für eine String-Spalte v1 liefert demnach folgende Bedingung eine cardinality auf Basis der Standardformel:
where to_number(v1) = 9
Wobei das to_number keine Rolle spielt, denn "where v1 = 9" wird genauso behandelt. Will man den Optimizer in einem solchen Fall weiter verwirren und die 1%-Schätzung für "function(column) = constant" zurückbekommen, dann kann man eine weitere Funktion ins Spiel bringen. Mit:
where sign(v1) = 1
bekommt man diese 1%-Schätzung, da der Optimizer in diesem Fall keine Vorstellung davon hat, was die sign-Funktion eigentlich tut. Ob man das irgendwo praktisch nutzen kann, sei mal dahingestellt - aber es zu wissen, kann sicher nicht schaden.

Natürlich funktionieren alle Beispiele nur so lange, wie v1 tatsächlich nur Repräsentationen numerische Werte enthält - und dann wäre es vermutlich naheliegend die Spalte gleich mit dem richtigen Datentyp auszustatten.

Montag, Juni 06, 2016

Merge Operationen und überflüssige Spalten.

Vor ein paar Jahren hatte ich hier einen Artikel von Alexander Anokhin verlinkt, in dem erläutert wurde, dass die in der USING clause eines Merge verwendeten Spalten selbst dann in die workarea aufgenommen werden müssen, wenn sie weder im ON noch in der UPDATE-Spaltenliste erscheinen - obwohl es eigentlich durch eine semantische Analyse möglich sein sollte zu bestimmen, dass man diese Spalten gefahrlos ausklammern könnte. Jetzt hat Jonathan Lewis auf einen naheliegenden anderen Aspekt dieses Effekts hingewiesen: dadurch, dass die Spalten in der Projection berücksichtigt werden, ist auch die Verwendung eines Index Fast Full Scans anstelle eines Full Table Scans nicht möglich, wenn zwischenzeitlich Spalten benötigt werden, die für die funktionale Ausführung der Operation eigentlich keine Rolle spielen.

Sonntag, Juni 05, 2016

SQL Server Wait Typen und Latch Klassen

Zwei großartige Hilfsmittel hat Paul Randal vor wenigen Wochen in seinem Blog bekannt gemacht:
  • SQL Server Wait Types Library: eine Liste mit den seit Version 2005 im SQL Server vorkommenden Wait Typen und Erklärungen zu ihrer Bedeutung, ihrer Verfügbarkeit, ihrer Beziehung zu des Extendes Events, sowie Informationen zum Troubleshooting.
  • SQL Server Latch Classes Library: mit entsprechenden Informationen zu den Latch Klassen.
Diese Links könnten mir allerlei Suchoperationen in Books Online ersparen.

Mittwoch, Juni 01, 2016

Datentypauswahl für Datumsangaben und ihre Wirkung auf den CBO

In Cost Based Oracle hat Jonathan Lewis dieses Thema bereits umfassend erläutert: Datumswerte sollten mit dem Datentyp DATE gespeichert werden, da der Optimizer nur für diesen Datentyp das Wissen besitzt, dass es zwischen den Monats- und Jahreswechseln keine großen Lücken gibt - dass also auf to_date('31.12.2016', 'dd.mm.yyyy') als nächster Tag to_date('01.01.2017', 'dd.mm.yyyy') folgt; und nicht 20161232 nach 20161231. Insofern enthält die aktuelle Artikelserie von Richard Foote zum gleichen Thema keine grundsätzlich neuen Einsichten, aber lesenswert sind die Artikel des Herrn Foote immer und man kann bei Bedarf gut darauf verlinken, so dass ich sie hier einfach aufliste: