Hacking für Skew Orakel Scratchpad Bitcoin aktuelle Preisvorstellung

In meiner Präsentation an die UKOUG SIG gestern “kämpft mit Statistiken – Teil 2” habe ich ein Problem beschrieben, das ich vor ein paar Monaten geschrieben habe: Wenn Sie eine Faktentabelle mit einer massiv verzerrten Verteilung auf einer der Ersatzschlüsselspalten zu einer Dimension verbinden Mit der eindeutigen Liste von Schlüsseln und Beschreibungen “verliert” eine Abfrage gegen eine Beschreibung den Skew. Hier ist eine Demo des Problems, die ein wenig einfacher als die im vorherigen Artikel ist.

Eine schnelle Überprüfung zeigt Ihnen, dass es 55 Zeilen für id_status = 10 gibt, was 55 Zeilen für status_code = ‘K’ bedeutet. Bitcoin-Konferenz 2018 also was passiert, wenn wir die beiden Abfragen schreiben, die uns diese Ergebnisse zeigen sollen. Größte Bitcoin Mining-Farm Mir ist es egal, was die Ausführungspläne zu diesem Zeitpunkt sind. Ich bin nur an der Kardinalität des Optimizers interessiert – also hier zwei Abfragen, jeder gefolgt von seinem Ausführungsplan:


Die geschätzte Kardinalität für die Abfrage der Basisspalte spiegelt den Wert 55 des Histogramms wider, aber die geschätzte Kardinalität des Joins beträgt 7.692 – was num_rows (facts) / num_distinct (id_status) ist. Oracle hat Informationen über die verloren schief. Graustufen-Investitionen Bitcoin Cash gibt es einen Weg zu bekommen Orakel um eine korrekte Schätzung (wie im vorherigen Artikel gezeigt) zu erzeugen, indem der Join als eine IN-Unterabfrage mit dem (undokumentierten) “precompute_subquery” -Hinweis umgeschrieben wird, aber es gibt eine Alternative, die David Kurtz Hypothese in einer Konversation, nachdem die Präsentation beendet war (tatsächlich hat jemand anderes ihre Verwendung genau seines vorgeschlagenen Ansatzes in einem Kommentar zu einer viel älteren Blognotiz über dieses Problem beschrieben): nimm das Histogramm aus der id_status Spalte in der Faktentabelle und ” Wenden Sie es auf die status_code-Spalte in der Status-Tabelle an. Im Gespräch mit David äußerte ich die Meinung, dass dies wahrscheinlich nicht funktionieren sollte, und es war nicht wirklich ein bisschen Fälschung, die ich auf ein Produktionssystem anwenden wollte – aber wir beide versuchten es, als wir nach Hause kamen … mit unterschiedlichen Graden des Erfolgs.

Der erste Schritt erhält die Spaltenstatistik von facts.Id_status – und ich weiß, dass ich ein Frequenzhistogramm habe, das genau die richtige Anzahl an unterschiedlichen Werten in dieser Spalte abdeckt, so dass fast alles richtig eingerichtet ist, um die Statistiken in Status zu kopieren. Status_code, außer eine Spalte ist numerisch und die andere ist ein Zeichen und (obwohl ich weiß, dass es wahr ist, weil ich die status_code-Werte definiert habe), muss ich sicherstellen, dass die Bucket-Werte, die ich in den status_code schreibe, in alphabetischer Reihenfolge angeordnet werden müssen Statuscode.

Also ist mein zweiter Schritt, eine Abfrage gegen die Faktentabelle auszuführen, um die Zählungen von status_code in alphabetischer Reihenfolge zu erhalten und die Ergebnisse in ein Paar von Arrays zu kopieren – eines davon ist ein eigenständiges Array des Typs, der im dbms_stats-Paket als Array definiert ist von Zeichentypen, die andere ist das Array von Bucket-Werte das ist bereits im stats record für die facts.Id_status-Spalte vorhanden, die ich in den Speicher gezogen habe. (das Bucket-Werte Array wird als kumulative Häufigkeitswerte gespeichert, daher muss ich sie an dieser Stelle mit den einfachen Häufigkeitswerten überschreiben).

Problem – das ist nicht was David Kurtz sah. In einer E-Mail an mich sagte er: “Zu meiner Überraschung, wenn ich ein Histogramm auf der Dimensionstabelle vortäusche, indem ich die Schräglage der Join-Spalte aus der Faktentabelle verwende, bekomme ich die korrekte Anzahl der im Ausführungsplan berechneten Zeilen kleiner als der Wert, wenn das Histogramm nicht vorhanden war) “. Wie kaufe ich Bitcoins in Großbritannien, um das konkret zu machen – als er nach ‘K’ fragte, bekam er die richtige Vorhersage, als er nach ‘D’ fragte, war er zurück zu einer Vorhersage von 7.692. Mit Blick auf den Bericht über die tatsächlichen Daten würde er das Richtige finden Prognose für die Codes ‘F’ bis ‘M’ und die falsche Vorhersage für die Codes ‘A’ bis ‘E’.

Wenn ich neue Tests starte, tendiere ich dazu, Oracle-Versionen in der Reihenfolge 12.1.0.2, dann 11.2.0.4, dann 12.2.0.1, dann 18.3.0.0 zu testen – es ist die Reihenfolge der Popularität, die ich derzeit sehe. Also habe ich meinen Test auf 12.1.0.2 ausgeführt; David hat seinen Test am 18.3.0.0 durchgeführt. Also bin ich einen Schritt gesprungen und habe meinen Test auf 12.2.0.1 ausgeführt: Hier sind meine Ergebnisse bei der Abfrage nach status_code = ‘D’:

Wie David mit 18.3 gesehen hat, benutzte Orakel das Num_Distinct, um die Kardinalität für ‘D’ zu schätzen. (Es verwendete immer noch den Wert, der durch das Histogramm für ‘K’ angezeigt wurde.) Wenn ich den Parameter optimizer_features_enable auf 12.1.0.2 zurücksetzte, ging die Kardinalitätsschätzung für ‘D’ auf 13.415 zurück – es sieht also so aus, als ob es sich um eine absichtliche Kodierung handelt . 172 Fix-Steuerelemente und 31 Optimizer-Statusparameter wurden geändert, aber keiner der wahrscheinlicheren Kandidaten hatte Auswirkungen, wenn ich sie separat testen wollte. Möglicherweise gibt es eine neue Plausibilitätsprüfung, wenn die Anzahl der für die Tabelle aufgezeichneten Zeilen weit von der Gesamtzahl der Histogramm-Buckets abweicht.