Überblick
Das MSSQL Feature, das es erlaubt, einen Nonclustered Index um zusätzliche Spalten zu erweitern, wird eingesetzt, um die Performance bestimmter Abfragen zu steigern: Erfolgt eine Abfrage über einen Nonclustered Index und benötigt man nur einen kleinen Teil der Spalten der zugrunde liegenden Tabelle, so erspart man sich den Zugriff auf die eigentliche Tabelle, da die benötigten Spaltendaten durch die Include-Klausel bereits in den jeweiligen Index-Knoten enthalten sind. In bestimmten Fällen - und hier trifft das immer wieder benötigte “it depends” zu - kann es zu unerwünschtem Verhalten kommen. Dies soll in diesem Beitrag näher beleuchtet werden.
Wo ist das Problem?
Die Verwendung von Include-Spalten führt zu einer erhöhten Transaktionsprotokollierung in der TLog Datei und dieses wird in den folgenden Unterkapiteln experimentell dargestellt.
Versuchsaufbau
Es werden zwei leere Datenbanken erstellt, die lediglich jeweils eine gleichnamige Tabelle enthalten:
Datenbank- bzw. Tabellenname:
- NonIncludedColumns
- IncludedColumns
In diese beiden Tabellen wird ein Testdatensatz eingefügt.
Um die durchgeführten Änderungen im TLog einfacher identifizieren zu können, werden
- unmittelbar vor der geplanten Test-Transaktion ein Checkpoint erstellt, so dass sich keine Dirty Pages mehr im Buffer Cache befinden
- unmittelbar vor der geplanten Test-Transaktion die Inhalte der TLog-Datei in eine temporäre Tabelle geschrieben. Hierzu wird die nicht dokumentierte Systemfunktion fn_dblog() verwendet
- unmittelbar nach der Test-Transaktion die Inhalte der TLog-Datei in eine zweite temporäre Tabelle geschrieben
- abschließend wird die Differenz der Inhalte der beiden temporären Tabellen gebildet und zwei der Spalten der Differenzmenge betrachtet
Um den hexadezimalen Inhalt des RowLogs leicht identifizieren zu können, werden für die drei Spalten die folgenden Inhalte Änderungen durchgeführt:
Wert10150x3ADAFA
Anlegen der Test-Datenbanken
Anlegen der Tabellen inkl. einer Zeile
Im nächsten Schritt wird in jeder der beiden neu erstellten Datenbanken eine Tabelle erstellt. Beide Tabellen haben die exakt gleiche Struktur, lediglich der Index auf der Spalte Indexspalte enthält in der einen Variante zwei inkludierte Spalten, IntWert und Binärwert. In beiden Tabellen wird eine Zeile angelegt. Zur Identifizierung im Transaktionslog werden die drei Spalten mit den Werten 1, 2 bzw. 0x3456789A initialisiert.
Änderung des Datensatzes
Im nächsten Schritt wird, wie bereits oben beschrieben, ein Checkppoint erstellt und der TLog-Inhalt mittels fn_dblog()
in eine temporäre Tabelle geschrieben. Anschließend erfolgt die Aktualisierung der Daten mit den markanten Werten 10 (0xA), 15 (0xF) und 0x3ADAFA (“MADAFA”).
Vergleich der Ergebnisse
Als Ergebnis haben wir jetzt die TLog-Informationen vor und nach Ausführung des Update Statements in den temporären Tabellen vorliegen. Hier bilden wir abschließend lediglich die Mengendifferenz der Tabelleninhalte, wobei uns in diesem Zusammenhang lediglich die Spalten [Log Record Length] und [RowLog Contents 0] interessieren.
Dem entsprechend selektieren wir
und erhalten u.a. die folgenden Ergebnisse, die lediglich im Fall der Included Columns das Muster 3ADAFA enthalten.
Die Ergebnisspalten der Funktion fn_dblog() sind übrigens sehr umfangreich und umfasssen in der hier verwendeten MSSQL Version 2022 insgesamt 124 Spalten. Von Interesse könnten für Sie evtl. auch die Spalten [Lock Information] und der gesamte Log-Datensatz [Log Record] sein, der hier wegen der Länge nicht wiedergegeben wurde.
Handelt es sich hier nur um DB-interne Information?
Man könnte jetzt argumentieren, dass es sich bei den von fn_dblog()
gelieferten Spalten ausschließlich um DB-interne Informationen handelt. Zum Nachweis, dass die TLog-Informationen im Fall der im Index inkludierten Spalten tatsächlich umfangreicher sind, als die eines Index ohne Icludes, wird der folgende Massentest durchgeführt:
Ergebnisse der Massentests
Die folgende Tabelle enthält die Ergebnisse der TLog-Dateigrößen in 8 kB Seiten nach Durchführung verschiedener Massentests. Es wurden mehrere Testreihen durchgeführt, nämlich
- mit den drei Kompatibilitätsstufen MSSQL 2016, MSSQL 2019 und MSSQL 2022
- mit implizitem Transaktions-Handling (= 10.000.000 einzelne Transaktionen)
- Massentest innerhalb einer einzelnen Transaktion (begin tran … commit)
Bezogen auf die Laufzeit der jeweiligen Tests hat sich kein signifikanter Unterschied ergeben. Hier ist zu bemerken, dass die Testreihen mit den vielen impliziten Transaktionen unabhängig von den Includes ungefähr 5 - 6 mal so lange dauerten, wie die Testreihen mit den einzelnen großen Transaktionen für den gesamten Testlauf.
Interessant hierbei sind die folgenden Beobachtungen:
- Die Verwendung von Included Columns macht sich nur in einer größeren TLog-Datei bemerkbar, wenn die Updates innerhalb nur einer Transaktion erfolgen. Im Fall der Include-Spalten ist die resultierende TLog-Datei ca. 4% größer (Testläufe 4, 5, 6 vs. 10, 11, 12).
- Bei Verwendung vieler impliziter Transaktionen ist keine Änderung der TLog-Größen zu verzeichnen (Testläufe 1, 2, 3 vs. 7, 8, 9).
- Der Wechsel von der Version 2019 zur Version 2022 hat bezüglich der Protokollierung der Transaktionen zu einer erheblichen Mehrprotokollierung geführt (Testläufe 2, 3, 8, 9 vs. 1, 7).
Kompatibilität202220192016202220192016202220192016202220192016
Wer ist betroffen?
Wie bereits erwähnt, hat sich durch die zusätzliche Protokollierung kein erkennbarer Performancenachteil in einer einzelnen Instanz ergeben. Trotzdem sollten bei kritischen Datenbanken folgende Punkte berücksichtigt werden
- Wieviele Transaktionen treten in der betrachteten Datenbank auf?
- Werden Transaktionsinformationen für eine / weitere Instanz(en) benötigt (Replikation, AlwaysOn Verfügbarkeitsgruppen)
- Welche Kapazität hat das Netzwerk über das die TLog-Informationen übertragen werden, gibt es hier bereits Engpässe?
- Bei extrem großen Datenbanken mit sehr vielen Transaktionen existieren auch Auswirkungen auf das TLog-Backup
- Hier wurde lediglich eine Include-Spalte verwendet. In welchem Umfang werden Include-Spalten eingesetzt?
Fazit
Im Zusammenhang mit der Verwendung von Include-Spalten existiert in bestimmten Fällen eine Abweichung der TLog-Protokollierung die im Normalfall nicht signifikant ist. Bei kritischen Datenbanken kann diese aber u.U. ins Gewicht fallen.
Wenn Sie mehr über dieses Thema erfahren möchten, stehen Ihnen unsere Expert:innen gerne zur Verfügung. Vereinbaren Sie gerne ein unverbindliches Beratungsgespräch über unser Kontaktformular.
Wir helfen Ihnen gerne weiter!