MS SQL-Server

Knowledge Base

MS SQL-Server > Datenbank-Funktionen > Indizierung

Was ist ein Heap?

Ein Heap ist eine von zwei Arten wie der MS SQL Server die Daten einer Tabelle speichern kann - entweder

  • Ungeordnet, als sogenannter Heap oder
  1. Geordnet, als gruppierten (clustered) Index

Achtung: Heaps haben beim MS SQL Server nur die Bedeutung einer ungeordneten "Anhäufung" (Heap = "Haufen") von Daten und sollten nicht mit der Heap-Datenstruktur verwechselt werden.

Standardmäßig erstellt MS SQL Server bei der Definition eines Primärschlüssels (primary key) für eine Tabelle automatisch auch einen gruppierten (clustered) Index (für die Schlüsselspalten des Primärschlüssels). Wird dieser entfernt (und kein neuer gruppierter (clustered) Index erstellt) oder wird die Tabelle ohne Primärschlüssel bzw. genauer ohne gruppierten (clustered) Index erstellt, dann werden die Daten ungeordnet (als Heap) gespeichert.

Die Reihenfolge der Daten sind bei einem Heap nicht vorhersagbar, weil sich der MS SQL Server vorbehält, die Daten jederzeit umsortieren zu können (z. B. um die Daten speicherschonender abzulegen) - d. h. die Daten sind nicht unbedingt in der Reihenfolge abgelegt, wie diese eingefügt worden sind (siehe auch hier). Wird die Ausgabe der Daten in einer bestimmten Reihenfolge gewünscht, muss die Reihenfolge mit ORDER BY bestimmt werden.

Die Verwendung eines Heaps ist u. U. effizienter als eine Tabelle mit einem gruppierten (clustered) Index. Inbesondere dann, wenn in die Tabelle hauptsächlich nur Einfüge-Operationen durchgeführt werden, z. B. bei einer Log-Tabelle, weil bei einem Heap keine Indexkorrekturen oder Suche nach der Einfügeposition durchgeführt werden müssen (die beim gruppierten (clustered) Index notwendig sind) - die Daten werden einfach ans Ende geschrieben.

Auch die Kombination von Heap und nicht-gruppierten (nonclustered) Indizes kann u. U. effizienter sein als die Kombination von gruppierten (clustered) Index  und nicht-gruppierten (nonclustered) Indizes - insbesondere dann, wenn der gruppierte (clustered) Index aus vielen oder großen Spalten besteht:

In diesem Fall werden diese Spalten bei den nicht-gruppierten (nonclustered) Indizes als Zeilenlokator (row locator) verwendet werden (anstatt der Zeilen ID (row ID) / 8 Bytes wie bei einem Heap) womit die nicht-gruppierten (nonclustered) Indizes weniger effizient werden (weil evtl. mehr Speicherplatz pro Eintrag verwendet wird und bei einem Treffer der Datensatz dann immer zusätzlich im gruppierten (clustered) Index gesucht werden muss - wenn die Abfrage nicht bereits durch den nicht-gruppierten (nonclustered) Index abgedeckt ist). Leider hängt diese Art der Optimierung (Heap + nicht-gruppierte (nonclustered) Indizes) sehr stark vom Anwendungsfall ab und die entsprechende Analyse lohnt sich oft nur bei sehr großen Tabellen.

Das SQL Server Management Studio (SSMS) selbst erstellt mit dem Primärschlüssel (primary key) automatisch einen gruppierten (clustered) Index, d. h. wird von diesem Standard abgewichen, sollte diese Änderung transparent für alle Entwickler im Team sein, weil sonst Wartungskosten / Performance-Einbußen durch falsche Annahmen entstehen können.


Erstellung einer Tabelle als Heap:

 --#region Remove Database [Test17]

USE [Master];
GO

IF DB_ID('Test17') IS NOT NULL
    ALTER DATABASE Test17 SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO

iF DB_ID('Test17') IS NOT NULL
    DROP DATABASE Test17;
GO

--#endregion

--#region Create Database [Test17]

CREATE DATABASE Test17;
GO

--#endregion

--#region Create table [TestHeap] as table without clustered index (= heap)

USE Test17;
GO

CREATE TABLE TestHeap
(
    [ID] INT IDENTITY(1,1) NOT NULL,
    TextColumn VARCHAR(100) NOT NULL
);
GO

--#endregion