SQL aktiviert keine Parallelität für extrem große Abfragen

7

Ich habe eine sehr große Abfrage (~ 630 Zeilen), die viele verschachtelte SELECTAnweisungen enthält und aus mehreren Ansichten abgerufen wird. Auf unserem SQL Server ist die Parallelität auf 2 mit einem Schwellenwert von 95 festgelegt (auf diese Weise festgelegt, weil unser DBA sie basierend auf einigen anderen Anwendungen optimiert hat). Diese Abfrage dauert seit kurzem 5-10 Minuten, normalerweise weniger als eine Minute. Bei der Untersuchung der Ursache haben wir festgestellt, dass sie niemals Parallelität auslöst, immer seriell ausgeführt wird und den Verdacht hat, dass dies etwas mit ihrer Leistung zu tun hat. Was seltsam ist, ist, dass wir beim Experimentieren den Schwellenwert sogar wieder auf den Standardwert von 5 Sekunden gesenkt haben und er immer noch nicht parallel läuft. Was könnte es verhindern?

Wir haben die Tests in einer Nicht-Produktionsumgebung durchgeführt, die zu diesem Zeitpunkt von niemand anderem verwendet wurde. Dies war also die einzige Abfrage, die ausgeführt wurde. Unser DBA versuchte auch Dinge wie das Löschen von Caches und Plänen und sogar das Recycling des Systems, aber es hatte keine Auswirkungen.

Update 1 : Gemäß Kommentaren habe ich überprüft, dass die Statistiken jede Nacht aktualisiert werden, aber das Problem besteht weiterhin. Wir führen den Code tatsächlich auf eine frühere Version zurück, die keine so schwerwiegenden Leistungsprobleme aufwies, werden diesen Code jedoch weiterhin testen, da er die Leistung gegenüber dem alten Code verbessern sollte und dies tatsächlich beim ersten Testen getan hat. Wird hier entsprechend aktualisiert.

Danke
quelle
Ich werde versuchen, die Statistiken zu aktualisieren, um festzustellen, ob sie Auswirkungen haben. Wenn nicht, werde ich das Trace-Flag ausprobieren und die Veröffentlichung des Plans / der Abfrage prüfen (vorausgesetzt, der DBA lässt mich zu, ist er damit möglicherweise nicht zufrieden).
Bis zum

Antworten:

17

Was seltsam ist, ist, dass wir beim Experimentieren den Schwellenwert sogar wieder auf den Standardwert von 5 Sekunden gesenkt haben und er immer noch nicht parallel läuft. Was könnte es verhindern?

Es gibt viele Gründe, warum der Optimierer keinen parallelen Plan erstellt (oder nicht erstellen kann). Breit:

  1. Offensichtliche Ursachen, z. B. die Konfiguration, bei der der maximale Parallelitätsgrad auf eins festgelegt wird, unter einer Resource Governor-Workload-Gruppe ausgeführt MAX_DOP = 1wird oder nur ein logischer Prozessor für SQL Server verfügbar ist
  2. Parallelitätshemmende Operationen

    Es gibt viele Operationen, die Parallelität verhindern, entweder weil sie in einem Parallelplan keinen Sinn ergeben oder weil das Produkt sie (noch) nicht unterstützt. Einige Beispiele (nicht erschöpfend!) Für Dinge, die den gesamten Plan zwingen, seriell zu sein:

    • Ändern des Inhalts einer Tabellenvariablen (Lesen ist in Ordnung)
    • Jede T-SQL-Skalarfunktion (die sowieso böse ist)
    • CLR-Skalarfunktionen, die als Datenzugriff gekennzeichnet sind (normale sind in Ordnung)
    • Einige Eigenfunktionen einschließlich OBJECT_NAME, ENCYPTBYCERTundIDENT_CURRENT
    • Schnellvorlauf-Cursor
    • Zugriff auf Systemtabellen (z. B. sys.tables )

    Jeder Verweis auf eine Tabelle (oder Ansicht) mit einer berechneten Spalte, die eine nicht inline T-SQL-Skalarfunktion verwendet, führt zu einem seriellen Plan, auch wenn auf diese Spalte in der Abfrage nicht verwiesen wird .

  3. Fehler bei der Kardinalitätsschätzung

    Wenn nichts die Parallelität in der Zielabfrage absolut verhindert, wählt der Optimierer möglicherweise immer noch eine serielle Alternative, wenn die geschätzten Kosten niedriger sind . Dies kann durch eine falsche Kardinalitätsschätzung verursacht werden.

  4. Kostenmodellbeschränkungen

    SQL Server verwendet ein Modell, um die Laufzeitkosten jedes Operators in einem Abfrageplan zu schätzen. Dieses Modell kann einen seriellen Plan falsch kosten, der billiger ist als die parallele Alternative. Der Optimierer wählt immer die billigste Option, die er in Betracht zieht.

    Wenn SQL Server einen parallelen Plan kostet, werden die CPU-Kosten für einen parallelen Iterator im Allgemeinen um einen Faktor reduziert, der dem erwarteten Laufzeit-DOP entspricht. Pläne mit Nested-Loops-Joins können ein besonderes Problem sein, da auf der Innenseite fast immer mehrere Threads seriell ausgeführt werden. Die Parallelitätssymbole sind weiterhin vorhanden, zeigen jedoch an, dass DOP-unabhängige serielle Threads vorhanden sind.

    Die Unterscheidung ist vielleicht subtil, aber sie erklärt (a), warum Operatoren, die normalerweise eine serielle Zone erzwingen, auf der Innenseite einer Schleifenverbindung "parallel" laufen können; und (b) der Optimierer reduziert die CPU-Kosten auf der Innenseite nicht um den geschätzten Laufzeit-DOP. Dies benachteiligt verschachtelte Schleifen bei der Parallelitätskostenberechnung im Vergleich zu Hash- und Merge-Joins und kann erklären, warum der Optimierer möglicherweise keinen Plan für parallele verschachtelte Schleifen auswählt.

  5. Probleme mit dem Codepfad des Optimierers

    Der Optimierer kommt möglicherweise überhaupt nicht so weit, einen parallelen Plan auszuwerten. Dies kann unter anderem dadurch geschehen, dass der endgültige Plan in der Phase des Trivialplans gefunden wird. Wenn ein Trivialplan möglich ist und die resultierenden Kosten unter dem konfigurierten Kostenschwellenwert für Parallelität liegen, werden die vollständigen Optimierungsphasen übersprungen und ein serieller Plan wird sofort zurückgegeben.

    Abfragen, die den Trivial Plan bestehen, können die Optimierung möglicherweise vorzeitig beenden (bevor die Parallelität berücksichtigt wird), entweder mit der Meldung " Gut genug Plan gefunden" oder mit einer Zeitüberschreitung . Beides sind Heuristiken, um zu verhindern, dass der Optimierer mehr Zeit für die Optimierung aufbringt, als er durch die Reduzierung der geschätzten Ausführungszeit (Kosten) gewinnen kann.

Testen

Es gibt keine unterstützte Möglichkeit, einen parallelen Plan zu erfordern, aber es gibt einige undokumentierte Tricks (nicht für die Produktion geeignet). Eine besteht darin, die während der Optimierung verwendete CPU-Gewichtung vorübergehend viel höher einzustellen, und die andere darin, das Ablaufverfolgungsflag 8649 zu setzen. Für SQL Server 2016 SP1 CU2 und höher führt der undokumentierte Abfragehinweis OPTION (USE HINT ('ENABLE_PARALLEL_PLAN_PREFERENCE'))dieselbe Funktion wie TF 8649 aus, jedoch ohne dass dies erforderlich ist Administratorrechte.

Der erstellte Plan ist möglicherweise nicht der Plan, den das Optimierungsprogramm normalerweise in Betracht zieht. Sie können ihn jedoch möglicherweise erfassen und nach sorgfältigen Tests und Überprüfungen in einem Planleitfaden für die Produktion verwenden.

Weitere Informationen finden Sie in meinem Artikel Erzwingen eines Ausführungsplans für parallele Abfragen und nicht parallelisierbare Vorgänge in SQL Server von Simon Sabin.

Paul White 9
quelle