Warum sollte der Operator Parallelität (Repartition Streams) die Zeilenschätzungen auf 1 reduzieren?

12

Ich verwende SQL Server 2012 Enterprise. Ich bin auf einen SQL-Plan gestoßen, der ein Verhalten aufweist, das ich nicht ganz intuitiv finde. Nach einem umfangreichen parallelen Index-Scan-Vorgang wird ein Parallelismus-Vorgang (Repartition Streams) ausgeführt, der jedoch die vom Index-Scan zurückgegebenen Zeilenschätzungen (Object10.Index2) beendet und die Schätzung auf 1 reduziert. Ich habe einige Suchvorgänge durchgeführt, aber Ich bin auf nichts gestoßen, was dieses Verhalten erklärt. Die Abfrage ist recht einfach, obwohl jede der Tabellen Datensätze in den niedrigen Millionenbereichen enthält. Dies ist Teil eines DWH-Ladeprozesses, und dieser Zwischendatensatz wird einige Male berührt, aber die Frage, die ich habe, bezieht sich insbesondere auf die Zeilenschätzungen. Kann jemand erklären, warum genaue Zeilenschätzungen innerhalb des Operators Parallelität (Repartition Strems) auf 1 gesetzt werden? Ebenfalls,

Ich habe den vollständigen Plan gepostet, um den Plan einzufügen .

Hier ist die fragliche Operation:

Bildbeschreibung hier eingeben

Einschließen des Plan-Baums für den Fall, dass mehr Kontext hinzugefügt wird:

Bildbeschreibung hier eingeben

Könnte ich auf eine Variation dieses Connect-Artikels stoßen, der von Paul White eingereicht wurde (weitere detaillierte Informationen auf seinem Blog hier )? Zumindest ist es das Einzige, was ich gefunden habe, das auch nur annähernd dem entspricht, was mir begegnet, obwohl es keinen TOP-Operator im Spiel gibt.

John Eisbrener
quelle

Antworten:

9

Abfragepläne mit Bitmap-Filtern sind manchmal schwierig zu lesen. Aus dem BOL-Artikel für Repartitionsströme (Hervorhebung meiner):

Der Operator "Repartition Streams" verwendet mehrere Streams und erstellt mehrere Streams von Datensätzen. Der Inhalt und das Format des Datensatzes werden nicht geändert. Wenn der Abfrageoptimierer einen Bitmapfilter verwendet, wird die Anzahl der Zeilen im Ausgabestream verringert.

Außerdem ist ein Artikel zu Bitmap-Filtern hilfreich:

Bei der Analyse eines Ausführungsplans mit Bitmap-Filterung ist es wichtig zu verstehen, wie die Daten durch den Plan fließen und wo die Filterung angewendet wird. Der Bitmap-Filter und die optimierte Bitmap werden auf der Seite der Build-Eingabe (der Dimensionstabelle) eines Hash-Joins erstellt. Die eigentliche Filterung wird jedoch in der Regel im Parallelitätsoperator durchgeführt, der sich auf der Seite der Probe-Eingabe (der Faktentabelle) des Hash-Joins befindet. Wenn der Bitmap-Filter jedoch auf einer Ganzzahlspalte basiert, kann der Filter direkt auf die erste Tabellen- oder Indexscanoperation und nicht auf den Parallelitätsoperator angewendet werden. Diese Technik wird als In-Row-Optimierung bezeichnet.

Ich glaube, das beobachten Sie bei Ihrer Anfrage. Es ist möglich, eine relativ einfache Demo zu erstellen, um einen Operator für Partitionsströme anzuzeigen, der eine Kardinalitätsschätzung reduziert, selbst wenn der Bitmap-Operator IN_ROWgegen die Faktentabelle verstößt. Datenvorbereitung:

create table outer_tbl (ID BIGINT NOT NULL);

INSERT INTO outer_tbl WITH (TABLOCK)
SELECT TOP (1000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM master..spt_values;

create table inner_tbl_1 (ID BIGINT NULL);
create table inner_tbl_2 (ID BIGINT NULL);

INSERT INTO inner_tbl_1 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

INSERT INTO inner_tbl_2 WITH (TABLOCK)
SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 2000000 - 2) NUM
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;

Hier ist eine Abfrage, die Sie nicht ausführen sollten:

SELECT *
FROM outer_tbl o
INNER JOIN inner_tbl_1 i ON o.ID = i.ID
INNER JOIN inner_tbl_2 i2 ON o.ID = i2.ID
OPTION (HASH JOIN, QUERYTRACEON 9481, QUERYTRACEON 8649);

Ich habe den Plan hochgeladen . Werfen Sie einen Blick auf den Operator in der Nähe von inner_tbl_2:

Partitionierung verliert Zeilen

Möglicherweise ist auch der zweite Test in Hash-Joins für nullbare Spalten von Paul White hilfreich.

Es gibt einige Inkonsistenzen bei der Anwendung der Zeilenreduzierung. Ich konnte es nur in einem Plan mit mindestens drei Tabellen sehen. Die Reduzierung der erwarteten Zeilen erscheint jedoch bei richtiger Datenverteilung sinnvoll. Angenommen, die verknüpfte Spalte in der Faktentabelle enthält viele wiederholte Werte, die in der Dimensionstabelle nicht vorhanden sind. Ein Bitmap-Filter kann diese Zeilen entfernen, bevor sie den Join erreichen. Für Ihre Abfrage wird die Schätzung auf 1 reduziert. Die Verteilung der Zeilen auf die Hash-Funktion liefert einen guten Hinweis:

row distro

Aufgrund dessen vermute ich, dass Sie viele wiederholte Werte für die Object1.Column21Spalte haben. Wenn die wiederholten Spalten nicht im Statistikhistogramm für enthalten sind, kann Object4.Column19SQL Server die Kardinalitätsschätzung sehr falsch berechnen.

Ich denke, dass Sie besorgt sein sollten, dass es möglich sein könnte, die Leistung der Abfrage zu verbessern. Wenn die Abfrage die Antwortzeit- oder SLA-Anforderungen erfüllt, ist eine weitere Untersuchung möglicherweise nicht sinnvoll. Wenn Sie jedoch weitere Nachforschungen anstellen möchten, gibt es ein paar Möglichkeiten (außer dem Aktualisieren von Statistiken), um eine Vorstellung davon zu erhalten, ob das Abfrageoptimierungsprogramm einen besseren Plan auswählen würde, wenn es bessere Informationen hätte. Sie könnten die Ergebnisse des Joins zwischen Database1.Schema1.Object10und Database1.Schema1.Object11in eine temporäre Tabelle stellen und sehen, ob Sie weiterhin Joins mit verschachtelten Schleifen erhalten. Sie können diesen Join in einen ändern, LEFT OUTER JOINdamit das Abfrageoptimierungsprogramm die Anzahl der Zeilen in diesem Schritt nicht verringert. Sie können MAXDOP 1Ihrer Abfrage einen Hinweis hinzufügen , um zu sehen, was passiert. Du könntest benutzenTOPzusammen mit einer abgeleiteten Tabelle, um den Join zum Letzten zu zwingen, oder Sie können den Join sogar aus der Abfrage auskommentieren. Hoffentlich reichen diese Vorschläge aus, um Ihnen den Einstieg zu erleichtern.

In Bezug auf das Verbindungselement in der Frage ist es äußerst unwahrscheinlich, dass es mit Ihrer Frage zusammenhängt. Dieses Problem hat nichts mit schlechten Zeilenschätzungen zu tun. Dies hat mit einer Racebedingung in Parallelität zu tun, die dazu führt, dass im Abfrageplan hinter den Kulissen zu viele Zeilen verarbeitet werden. Hier sieht es so aus, als würde Ihre Anfrage keine zusätzliche Arbeit leisten.

Joe Obbish
quelle
6

Das Hauptproblem hierbei ist eine schlechte Kardinalitätsschätzung für das Ergebnis des ersten Joins. Dies kann viele Gründe haben, am häufigsten handelt es sich jedoch entweder um veraltete Statistiken oder um eine Reihe korrelierter Join-Prädikate, von denen das Standardmodell des Optimierers annimmt, dass sie unabhängig sind.

In letzterem Fall ist UPDATE: Schlechte Leistung beim Ausführen einer Abfrage, die korrelierte UND-Prädikate in SQL Server 2008 oder SQL Server 2008 R2 oder SQL Server 2012 enthält, möglicherweise relevant, wenn das unterstützte Ablaufverfolgungsflag 4137 verwendet wird. Sie können die Abfrage auch mit ausführen Trace-Flag 4199 zum Aktivieren von Optimierungskorrekturen und / oder 2301 zum Aktivieren von Modellierungserweiterungen. Es ist schwer zu wissen, auf der Grundlage eines anonymisierten Plans.

Das Vorhandensein der Bitmap wirkt sich nicht direkt auf die Schätzung der Kardinalität des Joins aus, macht ihren Effekt jedoch früher sichtbar, indem eine frühe Semijoin-Reduzierung angewendet wird. Ohne die Bitmap wäre die Kardinalitätsschätzung für den ersten Join dieselbe und der Rest des Plans würde weiterhin entsprechend optimiert.

Wenn Sie neugierig sind, können Sie auf einem Testsystem Bitmaps für die Abfrage mit dem Ablaufverfolgungsflag 7498 deaktivieren. Sie können auch optimierte Bitmaps deaktivieren (vom Optimierer berücksichtigt und die Kardinalitätsschätzungen beeinflusst) und sie durch Bitmaps nach der Optimierung ersetzen (nicht berücksichtigt) vom Optimierer keine Auswirkung auf die Kardinalität) mit einer Kombination der Ablaufverfolgungsflags 7497 und 7498. Weder wird die Verwendung auf einem Produktionssystem dokumentiert noch unterstützt, aber sie erstellen Pläne, die der Optimierer normalerweise berücksichtigen könnte, und können daher mit einem erzwungen werden Plananleitung.

Nichts davon wird das Kernproblem der schlechten Schätzung für den ersten Beitritt lösen, wie oben erwähnt, so dass ich es wirklich nur aus Interessengründen erwähne.

Weitere Informationen zu Bitmaps und Hash-Joins:

Paul White 9
quelle
0

hat dir auf Twitter geantwortet. Ich habe mir die angehängte XML angesehen und sehe eine unausgeglichene Parallelität. Ein Thread enthält fast alle aktuellen Zeilen, die meisten anderen nicht. Das schreit nach unausgeglichener Parallelität. Daher würde ich den Schlüssel- / Verknüpfungswert und seine jeweilige Statistik und Kardinalität untersuchen.

Ihrer anderen Vorstellung nach bin ich mir nicht so sicher, ob das Connect-Element zutrifft, da Ihr eingefügter Plan nirgendwo, wo ich es gesehen habe, TOP enthält.

SQLBek
quelle