it-swarm.com.de

Erstellen Sie einen sehr großen Primärschlüsselindex neu

Ich habe eine SQL-Datenbank, die auf Azure gehostet wird. Das Problem ist, dass die Größe außer Kontrolle gerät. Ich kann eine Fragmentierung von bis zu 99% in den Cluster-Indizes des Primärschlüssels feststellen.

Ich kann alle anderen Indizes mit der Option online=on Neu erstellen und die Leistung wird dadurch nicht beeinträchtigt. Die Größe eines der PK-Clustered-Indizes ist größer als 200 GB, und für diesen Index bewirkt eine REBUILD...WITH (ONLINE=ON) eine Sperrung.

Wir haben Benutzer aus allen Zeitzonen, die auf die Site zugreifen. Daher kann ich keine Zeit finden, in der ich den Index offline neu erstellen kann.

Was ist die beste Strategie, um große Indizes ohne Ausfallzeiten auf der Site neu zu erstellen?

Ich glaube, eine Reorganisation wird nicht helfen, da die Fragmentierung 99% beträgt. Das Problem ist, dass die Tabelle auch online gesperrt wird. Das Hauptproblem ist, dass der Index größer als 200 GB ist. Der Primärschlüssel ist eine Ganzzahl.

13
Techy

Auch wenn es etwas spät ist, werde ich eine Antwort mit der Hoffnung einreichen, dass dies hilft oder zumindest einige zusätzliche Ideen/Kommentare zu diesem Thema verschmäht, da ich denke, dass dies eine gute Frage ist.

Erstens, und ich weiß nicht, ob Sie dies tun oder nicht, aber gehen Sie bitte nicht davon aus, dass hohe Fragmentierungsstufen im Index immer zu einer schlechten Leistung führen. Veraltete Statistiken (z. B. sys.dm_db_stats_properties ) und große Mengen an Leerraum pro Seite (d. H. Spalte avg_page_space_used_in_percent in sys.dm_db_index_physical_stats dmv ) sind in Bezug auf Leistungsprobleme relevanter als Fragmentierung allein. Ja, stark fragmentierte Indizes generieren mehr Read-Aheads und Sie sehen normalerweise veraltete Statistiken und höhere Leerzeichen pro Seite in Verbindung mit Fragmentierung, aber die Fragmentierung ist weder direkt mit der Optimierung des Abfrageplans verbunden, noch wie Viel Speicher, der den Index von der Festplatte lädt, wird tatsächlich verbraucht. Abfragepläne sind von Statistiken betroffen und Ihr Speicherbedarf wird mit mehr Leerraum aufgebläht. Zum Beispiel ein Index, der zu 99% fragmentiert ist, aber einen Durchschnitt von weniger als 5% aufweist. Leerzeichen und aktuelle Statistiken verursachen wahrscheinlich keine drastischen Leistungsprobleme im Vergleich zu einem schlechten Ausführungsplan aufgrund veralteter Statistiken oder einem ständigen Paging eines Index, der zu groß ist, um vollständig in den Speicher zu passen, da eine erhebliche Menge vorhanden ist pro Seite vorhandener Leerraum.

Wenn Fragmentierung wirklich ein Problem ist , können Sie es ONLINE reduzieren, indem Sie ein ALTER INDEX ... REORGANIZE Aussage wie von Dan Guzman in den Kommentaren identifiziert. Dadurch wird kein Index so rationalisiert wie bei einer REBUILD -Operation, aber die Fragmentierung wird verringert. Der Schlüssel hier besteht darin, Fenster mit geringerer Nutzung in Ihrer Datenbank zu identifizieren und diese dann auszuführen. Dies kann 15 Minuten oder mehrere Stunden dauern. Je länger, desto besser. Der Schlüssel hier ist jedoch, dass dieser Vorgang nicht rückgängig gemacht wird und alle erzielten Fortschritte beibehalten werden, selbst wenn Sie ihn während der Ausführung beenden.

Wenn es in einer perfekten Welt, in der Ihre Fragmentierung beseitigt wurde, sinnvoller wäre, die Partitionierung für diese Tabelle zu verwenden? Azure SQL Database allow für die Tabellenpartitionierung und Microsoft hat einen großartigen Artikel mit einigen Partitionierungsstrategien für die Azure SQL-Datenbank . Wenn Ihre Daten nichtflüchtig sind, kann eine Partitionierung dazu beitragen, den Wartungsaufwand zu verringern. In Verbindung mit Tabellenkomprimierung können Sie möglicherweise sogar Ihren gesamten Speicherbedarf reduzieren. Alberto Murillos frühere Antwort spielt auf die Verwendung von horizontale Partitionierung basierend auf einem Datenbereich an, und dieser Ansatz kann dazu beitragen, einige Wartungsfenster für Sie zu erstellen, da Ihre Daten regional spezifischer wären als global.

Der Übergang zu einer partitionierten Tabelle ist nicht einfach, da derzeit keine Wartungsfenster vorhanden sind. Möglicherweise können Sie jedoch einen von Maria Zakourdaev beschriebenen Ansatz verwenden, der Partitionierte Ansichten verwendet den oberen Rand Ihrer aktuellen Tabelle und eine neue partitionierte Tabelle, um zukünftige Daten zu partitionieren. Im Laufe der Zeit (und hoffentlich werden Ihre alten Daten gelöscht) können Sie schließlich vollständig auf die partitionierte Tabelle übergehen. Auch hier kenne ich Ihre Daten oder Ihre Anwendung nicht, aber vielleicht können Sie diesen Ansatz anwenden.

9
John Eisbrener

Zunächst ist es wichtig zu prüfen, ob Fragmentierung wichtig ist.

Wenn Ihre Abfrage nur einzeilige Suchvorgänge ausführt, bemerken Sie möglicherweise überhaupt keine Fragmentierung. In modernen SANs können durch das Caching auf SAN-Ebene phyiskale E/A-Vorgänge schnell genug ausgeführt werden, sodass die Fragmentierung keine Rolle spielt. Auf SSD kann das zufällige Muster IO), das durch das Scannen eines fragmentierten Index verursacht wird, tatsächlich zu einer besseren Leistung führen als nicht fragmentiert Daten.

Oft bemerken die Leute, dass die Neuerstellung eines Index ein Leistungsproblem behoben hat. Durch die Neuerstellung eines Index werden auch neue Statistiken erstellt. Es kann sein, dass der eigentliche Fix frische Statistiken sind und nicht den Index neu erstellen. UPDATE STATISTICS...WITH FULLSCAN Ist möglicherweise eine billigere, schnellere und weniger aufdringliche Methode, um dasselbe Leistungsproblem zu lösen.

Wenn Sie keine durch Fragmentierung verursachten Probleme haben, müssen Sie möglicherweise viel Zeit und Mühe aufwenden, um keinen tatsächlichen Gewinn zu erzielen.

Zweitens gibt es zwei Arten der Fragmentierung:

  1. Physische Fragmentierung. Daran denken die meisten Menschen, wenn sie an Fragmentierung denken. Die Seiten sind nicht in Ordnung und müssen neu bestellt werden. Wenn scannen ein Index ist, kann diese Art der Fragmentierung manchmal ein Problem sein. Ich habe allgemein festgestellt, dass dies mit physisch Lesevorgängen den größten Einfluss auf die Leistung hat. Wenn Sie sich die Ergebnisse von sys.dm_db_index_physical_stats Betrachten, ist diese Zahl die Spalte avg_fragmentation_in_percent.

  2. Fragmentierung mit geringer Dichte. Diese Fragmentierung wird durch Seiten verursacht, die nur teilweise mit Daten gefüllt sind. Sie haben geringe Dichte Daten, da Ihre Daten auf mehr Seiten als nötig verteilt sind. Infolgedessen erfordert das Lesen der Daten mehr E/A, da die Daten auf mehr Seiten als erforderlich verteilt sind. Dies kann sich sowohl auf logische als auch auf physische Lesevorgänge auswirken. Wenn Sie sich die Ergebnisse von sys.dm_db_index_physical_stats Betrachten, ist diese Zahl die Spalte avg_page_space_used_in_percent. Diese Spalte wird nur ausgefüllt, wenn der Modus SAMPLED oder DETAILED verwendet wird.

Was tun Sie dagegen?

Physische Fragmentierung : Wenn Sie einfach hohe Zahlen für avg_fragmentation_in_percent Verfolgen, sollten Sie wirklich überlegen, ob Sie Ihre Zeit verschwenden. Stellen Sie sicher, dass Sie eine tatsächliche Abfrage haben, die schlecht funktioniert, und verwenden Sie eine Testumgebung, um zu bestätigen, dass Sie ein Problem beheben, indem Sie die Fragmentierung beseitigen.

Sie können die physische Fragmentierung mit ALTER INDEX...REORGANIZE Behandeln. Die Operation REORGANIZE ist online und verschiebt die Seiten nacheinander, um sie wieder in physische Reihenfolge zu bringen. Wenn Sie eine REORGANIZE -Anweisung teilweise beenden, wird jede bereits ausgeführte Arbeit beibehalten - nur die eine Seite, die gerade verschoben wird, wird zurückgesetzt. Das Ausführen eines REORGANIZE für eine große Tabelle, die stark fragmentiert ist, kann mehr Speicherplatz für das gesamte Transaktionsprotokoll erfordern und im vollständigen Wiederherstellungsmodus möglicherweise eine erhebliche Anzahl von Transaktionsprotokollsicherungen generieren. Es kann auch länger dauern, bis ein stark fragmentierter Index REORGANIZE ist als REBUILD.

Sie werden häufig Ratschläge erhalten, ein REBUILD für stark fragmentierte Indizes anstelle eines REORGANIZE durchzuführen. Dies liegt daran, dass die Neuerstellung von Grund auf effizienter sein kann. Eine Reorganisation kann jedoch eine "onlineere" Operation sein und wird manchmal sogar für stark fragmentierte Indizes bevorzugt.

Fragmentierung mit niedriger Dichte kann nicht durch REORGANIZE behoben werden. Es kann nur durch Ausführen eines ALTER INDEX...REBUILD Behoben werden. Wenn Sie den Index mit ONLINE=ON Ausführen, sollten Sie in der Lage sein, das Blockieren zu minimieren. Das REBUILD muss jedoch noch einen Moment gesperrt werden, um den alten Index gegen den neuen Index auszutauschen. In einem sehr ausgelasteten System kann das Erreichen dieser exklusiven Sperre manchmal ein Problem sein. Sie sollten in der Lage sein, zu bestätigen, ob Sie dieses Problem haben, indem Sie sp_whoisactive verwenden, um die Blockierung während Ihrer Neuerstellung zu untersuchen und die Details der Sperren und Wartezeiten zu überprüfen. Die Verwendung der Option WAIT_AT_LOW_PRIORITY Kann hilfreich sein, wenn Sie wissen, dass eine geringe Auslastung bevorsteht und sich Ihre Neuerstellung für diesen Tausch "einschleichen" kann, wenn die Aktivität niedrig genug ist, um diese Sperre zu erreichen. Beachten Sie, dass eine lang laufende REBUILD -Operation auch eine lange laufende offene Transaktion sein wird. Offene Transaktionen mit langer Laufzeit können ihre eigenen Probleme haben, die mit der Verwendung/Wiederverwendung von Transaktionsprotokollen zusammenhängen. Wenn Sie Spiegelungs- oder Verfügbarkeitsgruppen verwenden, gibt es auch Überlegungen zum Wiederherstellen des Transaktionsprotokolls auf dem sekundären Replikat.

4
AMtwo

Hinweis

Nach diesem Kommentar:

Sie verlieren Zeilen, die während des Kopierens eingefügt werden. Wenn Sie dies verhindern möchten, indem Sie die Tabelle sperren, haben Sie das gleiche Problem wie das in seiner Frage angegebene OP. Auch 200Gb werden nicht kostenlos kommen :-) - Marco 5. September 17 um 11:18

... Ich sehe, wie dieser Ansatz nicht funktionieren wird.

Ich lasse diese Antwort als Beispiel dafür, was nicht zu tun ist.


Wenn in Ihrer Azure-Datenbank mehr als 200 GB frei sind, können Sie sich mit der "Neuerstellung" abfinden, indem Sie Ihre Daten in eine völlig neue Tabelle kopieren und dort bestellen.

Versuchen:

  • skripten Sie Ihr LiveTable in ein leeres NewTable
  • kopieren des LiveTable in das NewTable
  • umbenennen von LiveTable in OldTable
  • umbenennen von NewTable in LiveTable

Verwenden Sie natürlich den Namen Ihrer Tabelle anstelle von LiveTable.

2
Oreo

Wenn ein Index gut gestaltet ist, sollten wir im Idealfall nicht mit dem Verriegelungsmechanismus herumspielen müssen.

Für mich klingt es so, als müssten Sie die Sperre akzeptieren, um den Clustered-Index zu defragmentieren. Wenn die Wahrscheinlichkeit groß ist, dass dies erneut auftritt, sollten Sie den Clustered-Index neu gestalten (er sollte eng, eindeutig, statisch und immer größer sein).

Ich bin nicht sicher, welche Version von SQL Server Sie verwenden, aber Sie könnten 2012 Folgendes versuchen:

  • SET DEADLOCK_PRIORITY LOW - Dies teilt der Engine mit, dass die Indexwiederherstellung das Deadlock-Opfer sein soll, wenn/falls eines auftritt.

  • MaxDOP = 1 - Der MaxDOP-Wert begrenzt die Gesamtzahl der logischen CPUs, die parallel zum Erstellen des Index verwendet werden (ab 2005 - nur Enterprise Edition).

Sie können auch die Konfiguration der Seiten-/Zeilensperren ändern, aber ich würde das nicht ohne Tests tun. Sie könnten die Sperre nur verschlimmern, insbesondere wenn es sich um einen schlecht gestalteten Index handelt.

Ab 2014 gibt es die folgende Option, mit der die Engine grundsätzlich angewiesen wird, andere Sitzungen fortzusetzen und die Online-Indexoperation zu warten:

(WAIT_AT_LOW_PRIORITY (MAX_DURATION = 1 MINUTES, ABORT_AFTER_WAIT = SELF))
1
GPep

Ich habe den gleichen Ansatz wie Oreo oben mit großem Erfolg verwendet! Das einzige, was fehlt, ist, dass Sie ein Aktualisierungsskript ausführen müssen, nachdem Sie die Daten kopiert und die letzte Umbenennung vorgenommen haben.

Das Update sieht folgendermaßen aus:

Insert from OldTable into LiveTable
  Where not exists (select From OldTable Where LiveTable.Key = OldTable.Key)

Wenn der Schlüssel eine Identitätsspalte ist, müssen Sie einen etwas anderen Ansatz verwenden.

0
SBB