Heap or not to Heap, das ist die Frage. Wenn man sich für einen Heap als Datenspeicher entscheidet, ist es wichtig, die Systemstrukturen zu kennen, mit denen Microsoft SQL Server die Daten verwaltet. Dieser Artikel beschäftigt sich mit den – für Heaps relevanten – internen Strukturen einer Datenbank, die wichtig sind, um Vor- und Nachteile von Heaps für die einzelnen Anwendungsszenarien zu erkennen.
Inhaltsverzeichnis
PFS-Seite
Eine Datenseite ist die grundlegende Einheit für die Speicherung von Daten in SQL Server. Eine PFS-Seite (Page Free Space) zeichnet auf, ob eine einzelne Seite zugewiesen wurde. Ebenfalls – und das gilt ausschließlich für Heaps – wird der belegte Speicherplatz für eine Datenseite protokolliert.
Vergleicht man einen Heap mit einem Index, kann man sich vorstellen, warum nur für Heaps diese Einschränkung gilt. Sobald Microsoft SQL Server neue Daten in einen Heap eintragen soll, muss Platz gesucht werden, wo die Daten gespeichert werden können. Für Indizes muss der freie Speicherplatz einer Seite nicht nachverfolgt werden, da der Platz für neue Zeilen durch das Schlüsselattribut festgelegt wird.
Konzeptionell ist jede Datenbankdatei in PFS-Intervallen aufgeteilt. Ein PFS-Intervall besteht aus 8.088 Datenseiten (64 MB). Anders als andere Systemseiten verwendet eine PFS keine Bitmaps sondern Bytemaps für die Verwaltung von Informationen.
Eine PFS-Seite verwendet 1 Byte für jede Datenseite und zeichnet unter anderem auf, zu wie viel Prozent die Seite gefüllt ist. Die Speicherung des Füllgrads einer Seite kann bei einem Heap das Bottleneck für eine erfolgreiche Implementierung sein. Microsoft SQL Server kennt für den Füllgrad nur 5 Zustände.
Status (Bits) | Füllgrad | Bytes |
---|---|---|
0x00 | 0% | 0 Bytes |
0x01 | >0% und <=50% | 1 Byte – 4.030 Bytes |
0x02 | >50% und <= 80% | 4.031 Bytes – 6.488 Bytes |
0x03 | >80% und <= 95% | 6489 Bytes – 7.657 Bytes |
0x04 | >95% | 7.658 Bytes – 8.060 Bytes |
Arbeitsweise von PFS-Seite
Das nachfolgende Beispiel zeigt das Zusammenspiel von PFS-Seite und Datenmanipulationen. Detaillierte Erläuterungen zu den einzelnen DML-Operationen werden in späteren Artikeln beschrieben.
-- Erstellen eines Heaps mit einer Satzlänge von
-- 4 Bytes + 400 Bytes + 7 Bytes = 411 Bytes
CREATE TABLE dbo.demo_table
(
Id INT NOT NULL IDENTITY(1, 1),
C1 CHAR(400) NOT NULL DEFAULT ('Test')
);
GO
Wird in die Tabelle ein neuer Datensatz eingetragen, können die verschiedenen Schritte aus dem Transaktionsprotokoll ausgelesen werden.
BEGIN TRANSACTION InsertRecord
GO
INSERT INTO dbo.demo_table DEFAULT VALUES;
SELECT Operation,
Context,
AllocUnitName,
[Page ID]
FROM sys.fn_dblog(NULL, NULL)
WHERE [Transaction ID] =
(
SELECT [Transaction ID]
FROM sys.fn_dblog(NULL, NULL)
WHERE [Transaction Name] = N'InsertRecord'
)
OR [Transaction ID] = N'0000:00000000'
ORDER BY
[Current LSN] ASC;
GO
COMMIT TRANSACTION;
GO
Nachdem ein neuer Datensatz auf die Seite 142 (0x8e) eingetragen wurde, hat sich der Füllgrad der Datenseite geändert. Diese Änderung wird in Schritt 7 in der PFS-Seite (0x01) dokumentiert.
DBCC TRACEON (3604);
DBCC PAGE (0, 1, 1, 3);
Berücksichtigt man die weiter oben genannten Füllgrade, so können insgesamt 9 Datensätze auf der Seite gespeichert werden, bevor erneut eine Aktualisierung der PFS-Seite vorgenommen werden muss.
Der Auszug aus dem Transaktionsprotokoll zeigt, dass während des Einfügeprozesses keine weiteren Aktualisierungen an der PFS-Seite vorgenommen wurden.
Werden weitere 9 Datensätze eingetragen, stellt sich die Transaktion vollkommen anders dar!
Sobald der 10. Datensatz auf der Datenseite gespeichert wird (Zeile 6), wird der Status auf der PFS-Seite aktualisiert, da der Grenzwert von 4.030 Bytes überschritten wurde. Der Füllgrad der PFS-Seite wird auf 80% erhöht. Die nächsten 6 Datensätze werden ohne Aktualisierung der PFS-Seite gespeichert, da die gesamte Speichermenge <= 6.576 Bytes ist.
Mit dem nächsten Datensatz wird diese Grenze erneut überschritten und die PFS-Seite wird aktualisiert, da nun 80% der möglichen Speicherkapazität belegt sind. Mit der Speicherung des 17. Datensatzes wird erneut ein Grenzwert überschritten und es ist erneut eine Aktualisierung der PFS-Seite auf 95% erforderlich. Nachdem alle Datensätze gespeichert wurden, stellt sich der Füllgrad der betroffenen Seite wie folgt dar:
Der letzte Datensatz wird auf einer neuen Datenseite gespeichert, da er – rechnerisch – nicht mehr auf die Datenseite 142 passt.
8.030 - (8.030 Bytes * 95%) = 401 Bytes
Organisation von Datenseiten in einem Heap
Datenseiten in einem Heap werden ohne Pointer (Referenzen) zur nachfolgenden oder vorherigen Datenseite der Tabelle gespeichert. Diese Referenzen sind in einem Heap nicht erforderlich, da es in der Natur des Heaps liegt, dass es keine vordefinierte Sortierung gibt. Welche Datenseiten zu einem Heap gehören, wird über die IAM-Seite (Index Allocation Map) verwaltet, wie auch alle anderen zeilenbasierten Strukturen (Clustered Index/NonClustered Index).
Um herauszufinden, welche Datenseiten Microsoft SQL Server für die Verwaltung der Tabelle verwendet, kann man die folgende Abfrage verwenden:
SELECT page_type_desc,
allocated_page_iam_page_id,
allocated_page_page_id,
previous_page_page_id,
next_page_page_id,
page_free_space_percent,
page_level
FROM sys.dm_db_database_page_allocations
(
DB_ID(),
OBJECT_ID(N'dbo.demo_table', N'U'),
0,
NULL,
N'DETAILED'
)
WHERE page_type_desc = N'IAM_PAGE'
ORDER BY
page_type DESC,
allocated_page_page_id ASC;
GO
In der IAM-Seite kann man sehr leicht erkennen, welche Datenseiten zur Tabelle gehören.
DBCC TRACEON (3604);
DBCC PAGE (0, 1, 190, 3);
GO
Wenn Microsoft SQL Server weiß, welche Datenseiten zur Tabelle gehören, können die Daten SEQUENTIELL in ihrer physikalischen Reihenfolge gelesen werden. Diese Technik nennt man „Index Allocation Scan“ und setzt ein paar Erfordernisse voraus, die ich in einem der nächsten Artikel zu Heaps beschreiben werde.
Zusammenfassung
In diesem Artikel habe ich die – für einen Heap – wesentlichen Systemobjekte und Strukturen beschrieben. Sie zu kennen und zu verstehen, ist ein wesentlicher Bestandteil für das Finden einer geeigneten Strategie pro/contra Heap-Strukturen in einer Datenbank.
Herzlichen Dank fürs Lesen!