Abfragen und Updates sind nach IndexOptimize extrem langsam

12

Database SQL Server 2017 Enterprise CU16 14.0.3076.1

Wir haben kürzlich versucht, von den standardmäßigen Wartungsjobs für den Index-Neuaufbau auf den Ola Hallengren zu wechseln IndexOptimize. Die Standardjobs für die Indexwiederherstellung liefen seit einigen Monaten ohne Probleme, und die Abfragen und Aktualisierungen arbeiteten mit akzeptablen Ausführungszeiten. Nach dem Ausführen IndexOptimizeauf der Datenbank:

EXECUTE dbo.IndexOptimize
@Databases = 'USER_DATABASES',
@FragmentationLow = NULL,
@FragmentationMedium = 'INDEX_REORGANIZE,INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationHigh = 'INDEX_REBUILD_ONLINE,INDEX_REBUILD_OFFLINE',
@FragmentationLevel1 = 5,
@FragmentationLevel2 = 30,
@UpdateStatistics = 'ALL',
@OnlyModifiedStatistics = 'Y'

Leistung war extrem verschlechtert. Eine Update-Anweisung, die zuvor IndexOptimize100 ms dauerte, dauerte danach 78.000 ms (unter Verwendung eines identischen Plans), und Abfragen führten auch zu einer Verschlechterung um mehrere Größenordnungen.

Da es sich bei dieser Datenbank immer noch um eine Testdatenbank handelt (wir migrieren ein Produktionssystem von Oracle), haben wir auf eine Sicherung zurückgegriffen und diese deaktiviert, IndexOptimizeund alles ist wieder normal.

Wir möchten jedoch verstehen, was IndexOptimizeanders als das "normale" Index RebuildVerhalten ist, das diesen extremen Leistungsabfall verursacht haben könnte, um sicherzustellen, dass wir ihn vermeiden, sobald wir in die Produktion gehen. Anregungen, wonach zu suchen ist, wären sehr dankbar.

Ausführungsplan für die Update-Anweisung, wenn sie langsam ist. dh
nach IndexOptimize
Ist-Ausführungsplan (so bald wie möglich)

Ich konnte keinen Unterschied feststellen.
Planen Sie für die gleiche Abfrage , wenn es schnell
Actual Ausführungsplan

Martin Bergström
quelle

Antworten:

11

Ich vermute, dass zwischen Ihren beiden Wartungsansätzen eine andere Abtastrate definiert wurde. Ich glaube, Olas Skripte verwenden die Standardabtastung, es sei denn, Sie geben den @StatisticsSampleParameter an , der momentan nicht so aussieht.

Zu diesem Zeitpunkt handelt es sich um Spekulationen. Sie können jedoch überprüfen, welche Abtastrate derzeit in Ihrer Statistik verwendet wird, indem Sie die folgende Abfrage in Ihrer Datenbank ausführen:

SELECT  OBJECT_SCHEMA_NAME(st.object_id) + '.' + OBJECT_NAME(st.object_id) AS TableName
    ,   col.name AS ColumnName
    ,   st.name AS StatsName
    ,   sp.last_updated
    ,   sp.rows_sampled
    ,   sp.rows
    ,   (1.0*sp.rows_sampled)/(1.0*sp.rows) AS sample_pct
FROM sys.stats st 
    INNER JOIN sys.stats_columns st_col
        ON st.object_id = st_col.object_id
        AND st.stats_id = st_col.stats_id
    INNER JOIN sys.columns col
        ON st_col.object_id = col.object_id
        AND st_col.column_id = col.column_id
    CROSS APPLY sys.dm_db_stats_properties (st.object_id, st.stats_id) sp
ORDER BY 1, 2

Wenn Sie sehen, dass dies durch eine 1 kommt (z. B. 100%), ist dies wahrscheinlich Ihr Problem. Vielleicht versuchen Sie es noch einmal mit Olas Skripten, einschließlich des @StatisticsSampleParameters mit dem Prozentsatz, der von dieser Abfrage zurückgegeben wird, und versuchen Sie, das Problem zu beheben.


Als zusätzlichen Beleg für diese Theorie zeigt das XML-Ausführungsplan-Beispiel sehr unterschiedliche Abtastraten für die langsame Abfrage (2.18233%):

<StatisticsInfo LastUpdate="2019-09-01T01:07:46.04" ModificationCount="0" 
    SamplingPercent="2.18233" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]" 
    Schema="[SVALA]" Database="[ulek-sva]" />

Gegen die schnelle Abfrage (100%):

<StatisticsInfo LastUpdate="2019-08-25T23:01:05.52" ModificationCount="555" 
    SamplingPercent="100" Statistics="[INDX_UPP_4]" Table="[UPPDRAG]" 
    Schema="[SVALA]" Database="[ulek-sva]" />
John Eisbrener
quelle
@ JoshDarnell LOL, dies ist das zweite Mal, dass Sie im Abfrageplan einige unterstützende Statistikinformationen gefunden haben, die ich nicht gesehen habe. Danke für die Bearbeitung!
John Eisbrener
Haha, ich habe vergessen, dass du das warst, John! Ich verspreche, ich stalke dich nicht 😅
Josh Darnell
@JoshDarnell Ich schätze die zusätzlichen Erkenntnisse und es ist eine weitere gute Erinnerung daran, dass die Ausführungspläne so viele Informationen enthalten, dass Sie sie einfach nicht überspringen sollten.
John Eisbrener
Froh, dass ich Helfen kann! Und ja, es gibt Dinge, die ich auch die ganze Zeit vermisse (ich bin von der Statistik-Sache verbrannt worden, also gehe ich eher schnell dorthin, um zu sehen, was los ist).
Josh Darnell
Vielen Dank für diese Erklärung, es war in der Tat das Problem. Die meisten Statistiken hatten eine Standardabtastrate von 2,2%, aber einige, die nach der Migration von Oracle erstellt wurden, hatten eine Abtastrate von 100%. Es scheint, dass die Standard-Index-Neuerstellung die 100% beibehielt, aber als wir IndexOptimize verwendeten, wendete es den Standard von 2,2% auch auf diese an. Durch Anwenden des Parameters @StatisticsSample und erneutes Ausführen der Abfragen wurde bestätigt, dass dies die Ursache für das Problem war.
Martin Bergström
5

Die Antwort von John ist die richtige Lösung. Dies ist nur eine Ergänzung zu den Teilen des Ausführungsplans, die geändert wurden, und ein Beispiel dafür, wie Sie die Unterschiede mit dem Sentry One Plan Explorer auf einfache Weise erkennen können

Eine Update-Anweisung, die 100 ms vor IndexOptimize benötigte, benötigte danach 78.000 ms (mit einem identischen Plan).

Wenn Sie sich alle Abfragepläne ansehen, bei denen sich die Leistung verschlechtert hat, können Sie die Unterschiede leicht erkennen.

Beeinträchtigte Leistung

Bildbeschreibung hier eingeben

Zwei Zählungen von über 35 Sekunden CPU-Zeit und verstrichener Zeit

Erwartete Leistung

Bildbeschreibung hier eingeben

Viel besser

Die Hauptverschlechterung bei dieser Aktualisierungsabfrage ist zweimal:

UPDATE SVALA.INGÅENDEANALYS
                           SET 
                              UPPDRAGAVSLUTAT = @NEW$AVSLUTAT
                        WHERE INGÅENDEANALYS.ID IN 
                           (
                              SELECT IA.ID
                              FROM 
                                 SVALA.INGÅENDEANALYS  AS IA 
                                    JOIN SVALA.INGÅENDEANALYSX  AS IAX 
                                    ON IAX.INGÅENDEANALYS = IA.ID 
                                    JOIN SVALA.ANALYSMATERIAL  AS AM 
                                    ON AM.ID = IA.ANALYSMATERIALID 
                                    JOIN SVALA.ANALYSMATERIALX  AS AMX 
                                    ON AMX.ANALYSMATERIAL = AM.ID 
                                    JOIN SVALA.INSÄNTMATERIAL  AS IM 
                                    ON IM.ID = AM.INSÄNTMATERIALID 
                                    JOIN SVALA.INSÄNTMATERIALX  AS IMX 
                                    ON IMX.INSÄNTMATERIAL = IM.ID
                              WHERE IM.UPPDRAGSID = SVALA.PKGSVALA$STRIPVERSION(@NEW$ID)
                      )

Der Ausführungsplan für diese Abfrage mit verminderter Leistung

Der geschätzte Abfrageplan dieser Aktualisierungsabfrage weist sehr hohe Schätzungen auf, als die Leistung beeinträchtigt wurde:

Bildbeschreibung hier eingeben

In Wirklichkeit (der tatsächliche Ausführungsplan) muss es noch funktionieren, nur nicht die verrückte Menge, die die Schätzungen zeigen.

Der größte Einfluss auf die Leistung sind die beiden folgenden Verknüpfungen von Scans und Hash-Matches:

Tatsächlicher Scan bei verminderter Leistung # 1

Bildbeschreibung hier eingeben

Tatsächlicher Scan bei verminderter Leistung # 2

Bildbeschreibung hier eingeben


Der Ausführungsplan für diese Abfrage mit der erwarteten Leistung

Wenn Sie dies mit den Schätzungen (oder tatsächlichen Werten) des Abfrageplans mit der normalen erwarteten Leistung vergleichen, sind die Unterschiede leicht zu erkennen.

Bildbeschreibung hier eingeben

Auch die beiden vorherigen Tabellenzugriffe sind nicht einmal aufgetreten:

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

Diese Beseitigung wird beim Hash-Join nicht angezeigt, da die Build-Eingabe (oben) zuerst in die Hash-Tabelle eingefügt wird. Anschließend werden in dieser Hash-Tabelle Nullwerte geprüft und Nullwerte zurückgegeben.

Randi Vertongen
quelle
1
Vielen Dank für die detaillierte Beschreibung der Pläne, es war sehr hilfreich für mein Verständnis, warum das Problem aufgetreten ist. Ich werde auf jeden Fall einen Blick auf Sentry One Plan Explorer werfen, es sieht sehr nützlich aus!
Martin Bergström
@ MartinBergström Das freut mich zu hören, vielen Dank für die Bereitstellung der Abfragepläne und die Bereitstellung aller relevanten Informationen, nach denen wir in den Kommentaren gefragt haben :). Das Beste am Plan Explorer ist, dass es kostenlos ist! Es kann auch von innerhalb von ssms aus funktionieren (indem Sie mit der rechten Maustaste auf den Ausführungsplan klicken und auf "Mit Sentryone Plan Explorer anzeigen" klicken).
Randi Vertongen
1

Ohne weitere Informationen können wir nur leicht informierte Stiche im Dunkeln durchführen. Bearbeiten Sie die Frage, um ein wenig mehr Informationen bereitzustellen. Beispielsweise können die Abfragepläne für diese Aktualisierungsanweisung, für die Sie vor und nach den Indexwartungsvorgängen die Zeitpläne angegeben haben, aufgrund der aktualisierten Indexstatistiken abweichen ( https://www.brentozar.com/pastetheplan) / ist nützlich, anstatt die Frage mit einem großen XML-Teil zu füllen oder einen Screen-Grab zu geben, der einige der relevanten Informationen, die der Text des Plans enthält, nicht enthält.

Zwei sehr einfache Punkte auf Anhieb:

  1. Ist der Optimierungslauf definitiv abgeschlossen? Wenn Ihre Tests mit dem IO von Indexneuerstellungen mit langer Laufzeit konkurrieren, hat dies Auswirkungen auf die Zeitplanung.
  2. Haben Sie mehrmals getestet? Wenn die Aktualisierung auf Daten aus einer Abfrage basiert, die viele Daten berücksichtigt (anstelle eines einfachen UPDATE TheTable SET ThisColumn = 'A Static Value'), befinden sich diese Daten normalerweise im Speicher, wurden jedoch gelöscht Die ersten Durchläufe verwandter Abfragen sind langsamer als gewöhnlich, da die Festplatte getroffen wird, anstatt die benötigten Seiten zu finden, die sich bereits im Pufferpool im Speicher befinden.
David Spillett
quelle
Vielen Dank, dass Sie sich die Zeit genommen haben, uns zu antworten. Ich habe die Frage mit pastetheplan Links aktualisiert. Die Optimierung war definitiv abgeschlossen und dauerte ca. 1 Stunde, bevor die Probleme auftraten. Wir haben mehrere Tests durchgeführt, und es waren tatsächlich zwei Kopien der Datenbank betroffen, die in zwei verschiedenen Testumgebungen auf dieselbe Weise ausgeführt wurden. Die Update-Anweisung war nur das einfachste Beispiel, das ich gefunden habe, es gab zahlreiche andere Einfügungen und Auswahlen betroffen
Martin Bergström
Mit "mehrfach" meinte ich, die Aktualisierungen nach einer Instanz der Indexänderungen mehrmals auszuführen, anstatt das Indexoptimierungsskript mehrmals unabhängig auszuführen (obwohl dies selbst eine nützliche Methode ist, um zu überprüfen, ob das Ergebnis reproduzierbar ist). Wenn das Leeren des Speichers das Problem ist (oder ein Teil davon ist), wird der Pufferpool durch die ersten Aktualisierungen von Selects vorgefüllt, sodass die späteren möglicherweise aufgrund einer erheblich verringerten E / A schneller sind.
David Spillett
Entschuldigung, wenn meine Antwort unklar war. Ja, wir haben die Updates mehrmals versucht. Die Verlangsamung trat in einer Datenbank auf, die von Testern zum Testen der Anwendung verwendet wurde, und die Abfragen und Aktualisierungen wurden mehrmals während des Tages ohne Leistungsverbesserung ausgeführt.
Martin Bergström