it-swarm.com.de

Warum belegen meine nicht gruppierten Indizes mehr Speicherplatz, wenn ich Zeilen lösche?

Ich habe eine große Tabelle mit 7,5 Milliarden Zeilen und 5 Indizes. Wenn ich ungefähr 10 Millionen Zeilen lösche, stelle ich fest, dass die nicht gruppierten Indizes die Anzahl der Seiten zu erhöhen scheinen, auf denen sie gespeichert sind.

Ich habe eine Abfrage gegen dm_db_partition_stats um den Unterschied (nach - vor) in Seiten zu melden:

(dm_db_partition_stats deltas

Index 1 ist der Clustered-Index, Index 2 ist der Primärschlüssel. Die anderen sind nicht gruppiert und nicht eindeutig.

Warum nehmen die Seiten in diesen nicht gruppierten Indizes zu?
Ich habe erwartet, dass die Zahlen im schlimmsten Fall gleich bleiben.
Ich sehe Leistungsindikatoren, die eine Zunahme der Seitenteilung während des Löschens melden.

Muss der Geisterdatensatz beim Löschen auf eine andere Seite verschoben werden? Hat das mit "Uniqueifiers" zu tun?

Wir sind gerade dabei, RCSI einzuführen, aber im Moment ist RCSI ausgeschaltet.

Es ist ein primärer Knoten in einer Verfügbarkeitsgruppe. Ich weiß, dass Snapshot irgendwie auf Secondaries verwendet wird. Ich wäre überrascht, wenn das relevant wäre. Ich habe vor, mich damit zu beschäftigen (siehe dbcc-Seitenausgabe), um mehr zu erfahren. Wir hoffen, dass jemand etwas Ähnliches gesehen hat.

23
Michael J Swart

Ein mögliches Szenario, das mich sehr amüsiert:

  • Die Zeilen wurden ursprünglich geschrieben, als in der Datenbank RCSI (Read Committed Snapshot), SI (Snapshot Isolation) oder AGs (Availability Groups) nicht aktiviert waren
  • RCSI oder SI wurde aktiviert oder die Datenbank wurde einer Verfügbarkeitsgruppe hinzugefügt
  • Während des Löschvorgangs wurde den gelöschten Zeilen ein 14-Byte-Zeitstempel hinzugefügt, um RCSI/SI/AG-Lesevorgänge zu unterstützen

Da dieser Server ein Primärserver in einer AG ist, ist er genauso betroffen wie die Sekundärserver. Die Versionsinformationen werden auf der Primärseite hinzugefügt - die Datenseiten sind sowohl auf der Primärseite als auch auf der Sekundärseite exakt gleich. Die Secondaries nutzen den Versionsspeicher, um ihre Lesevorgänge durchzuführen, während die Zeilen von der AG aktualisiert werden. Die Secondaries schreiben jedoch keine eigenen Versionen des Zeitstempels auf die Seite. Sie erben nur die Versionen von der Arbeit des Primärs.

Um das Wachstum zu demonstrieren, habe ich den Stack Overflow-Datenbankexport (für den RCSI nicht aktiviert ist) verwendet und eine Reihe von Indizes für die Posts-Tabelle erstellt. Ich habe die Indexgrößen mit sp_BlitzIndex @Mode = 2 überprüft (in eine Tabelle kopieren/einfügen und ein wenig bereinigen, um die Informationsdichte zu maximieren):

(sp_BlitzIndex before

Ich habe dann ungefähr die Hälfte der Zeilen gelöscht:

BEGIN TRAN;
DELETE dbo.Posts WHERE Id % 2 = 0;
GO

Amüsanterweise wuchs die Datendatei während der Löschvorgänge, um auch die Zeitstempel aufzunehmen! Der SSMS-Datenträgerverwendungsbericht zeigt die Wachstumsereignisse - hier nur zur Veranschaulichung:

(Growth events

(Ich muss eine Demo lieben, in der durch Löschen die Datenbank wächst.) Während das Löschen ausgeführt wurde, habe ich sp_BlitzIndex erneut ausgeführt. Beachten Sie, dass der Clustered-Index weniger Zeilen enthält, seine Größe jedoch bereits um etwa 1,5 GB gewachsen ist. Die nicht gruppierten Indizes auf AcceptedAnswerId sind dramatisch gewachsen - sie sind Indizes mit einem kleinen Wert, der größtenteils null ist, sodass sich ihre Indexgrößen fast verdoppelt haben!

(sp_BlitzIndex during deletion

Ich muss nicht warten, bis der Löschvorgang abgeschlossen ist, um dies zu beweisen, also werde ich die Demo dort stoppen. Der Punkt ist: Wenn Sie große Löschvorgänge für eine Tabelle ausführen, die implementiert wurde, bevor RCSI, SI oder AGs aktiviert wurden, können die Indizes (einschließlich des Clusters) tatsächlich vergrößert werden, um das Hinzufügen des Zeitstempels für den Versionsspeicher zu ermöglichen.

29
Brent Ozar