Was sind gültige Nutzungsszenarien für HEAP-Tabellen?

31

Ich führe derzeit einige Datenimporte in ein Altsystem durch und habe festgestellt, dass dieses System keinen einzelnen Clustered-Index verwendet. Eine schnelle Google-Suche führte mich in das Konzept der HEAP-Tabellen ein. Jetzt bin ich gespannt, in welchen Nutzungsszenarien eine HEAP-Tabelle einer gruppierten Tabelle vorzuziehen ist.

Soweit ich verstanden habe, wäre eine HEAP-Tabelle nur für Audittabellen nützlich und / oder wenn Einfügungen weitaus häufiger vorkommen als ausgewählte. Dies spart Speicherplatz und Festplatten-E / A, da kein Clustered-Index verwaltet werden muss und die zusätzliche Fragmentierung aufgrund der sehr seltenen Lesevorgänge kein Problem darstellt.

marc.d
quelle
1
Sprechen Sie über SQL Server?
a_horse_with_no_name
@a_horse_with_no_name ja, ich vergaß , dass sry zu erwähnen
marc.d
Heap-Tabellen eignen sich für Tabellen mit Millionen von Zeilen, die stark von Benutzern betroffen sind. Der Nachteil ist, dass sie viel Platz einnehmen können, da die Daten physisch unsortiert gespeichert werden. Außerdem verlassen Sie sich darauf, dass Ihre Indizes auf Ihre Abfragen abgestimmt sind. Ich habe an Orten gearbeitet, die aufgrund von Leistungsproblemen überhaupt keine Clustered-Indizes verwendeten. Wahrscheinlich aufgrund einer schlechten Auswahl an Clustered-Indizes, aber wenn Sie nur Heap-Tabellen verwenden, müssen Sie sich darüber keine Gedanken machen. Eine bessere Lösung wäre, die Enterprise Edition von SQL Server zu verwenden und die große Tabelle horizontal zu partitionieren. Aber wenn Sie nicht die ent
Siehe auch stackoverflow.com/questions/1341393/… .
Jon of All Trades

Antworten:

22

Die einzig gültigen Verwendungen sind für

  • Staging-Tabellen, die in Import- / Export- / ETL-Prozessen verwendet werden.
  • Ad-hoc, temporäre und kurzfristige Sicherung von Tabellen mit SELECT * INTO..

Staging-Tabellen sind in der Regel recht flach und werden vor / nach der Verwendung abgeschnitten.

Beachten Sie, dass ein Clustered-Index im Vergleich zur Datengröße in der Regel nur wenige klein ist: Die Daten sind die niedrigste Ebene der Indexstruktur.

Heap-Tabellen haben auch Probleme. Zumindest diese:

  • kann nicht defragmentiert werden, um Speicherplatz auf der Festplatte zu reduzieren. Dies ist wichtig, da die verwendeten Datenseiten beispielsweise über die gesamte MDF verteilt sind, da die Daten keine "Reihenfolge" im Clustered-Index aufweisen
  • Nicht gruppierter Index zeigt jetzt auf die Zeile, nicht auf den Eintrag für den gruppierten Index. Dies wirkt sich auf die Leistung aus: Daten müssen über einen Clustered-Index mit einem Nicht-Clustered-Index abgerufen werden

Siehe auch

gbn
quelle
2
Normalerweise werden Haufen für zwei verschiedene Dinge verwendet. ETL-Staging- und -Arbeitstabellen, mit denen ich Daten temporär speichere, wenn die Menge zu groß ist, damit eine temporäre Tabelle effektiv funktioniert. Alle werden beim nächsten Laden abgeschnitten.
Zane
Gute Frage übrigens.
Zane
1
Eine kleine Änderung: Wenn Sie SELECT INTO ausführen, um eine schnelle Sicherung einer kleinen Tabelle zu erstellen, bevor Sie eine Änderung vornehmen, wird standardmäßig ein Heap erstellt. Ich würde sagen, das ist eine gültige Verwendung - aber das ist nur eine Fehlentscheidung. Ich würde diesen Haufen loswerden wollen, sobald ich wusste, dass meine Arbeit erledigt war.
Brent Ozar
@BrentOzar: Einverstanden, ich mache das die ganze Zeit selbst. Der Geist meiner Antwort ist „langfristige und persistente Tabellen“ aber ich werde aktualisieren
GBN
9

Wichtige Überlegungen

Ich sehe einen wichtigen Vorteil für Heaps und einen für gruppierte Tabellen sowie eine dritte Überlegung, die in beide Richtungen gehen kann.

  • Ein Haufen erspart Ihnen eine Indirektionsebene. Indizes enthalten Zeilen-IDs, die direkt (also nicht wirklich, aber so direkt wie möglich) auf einen Speicherort verweisen. Daher sollte eine Indexsuche für einen Heap ungefähr die Hälfte einer nicht gruppierten Indexsuche für eine gruppierte Tabelle kosten.

  • Ein Clustered-Index wird per se dank eines (fast) freien Index sortiert. Da sich der Clustering-Index in der physischen Reihenfolge der Daten widerspiegelt, nimmt er relativ wenig Platz über den eigentlichen Daten selbst ein, was Sie natürlich trotzdem speichern müssen. Aufgrund der physischen Reihenfolge kann ein Entfernungsscan anhand dieses Index sehr effizient nach dem Startpunkt suchen und dann bis zum Endpunkt zippen.

  • Heap-Indizes verweisen auf 64-Bit-RIDs. Wie bereits erwähnt, verweisen die nicht gruppierten Indizes in einer gruppierten Tabelle auf den Clustering-Schlüssel, der kleiner (32 Bit INT), gleich (64 Bit BIGINT) oder größer (48 Bit DATETIME2()plus 32 Bit) sein INTkann. oder eine 128-Bit-GUID). Offensichtlich führt eine breitere Referenz zu größeren und teureren Indizes.

Platzanforderungen

Mit diesen beiden Tabellen:

CREATE TABLE TmpClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpClustered ADD CONSTRAINT PK_Tmp1 PRIMARY KEY CLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp1 ON TmpClustered (ID2)

CREATE TABLE TmpNonClustered
(
ID1 INT NOT NULL,
ID2 INT NOT NULL
)
ALTER TABLE TmpNonClustered ADD CONSTRAINT PK_Tmp2 PRIMARY KEY NONCLUSTERED (ID1)
CREATE UNIQUE INDEX UQ_Tmp2 ON TmpNonClustered (ID2)

... jeder mit 8,7 M Datensätzen bestückt war, war der Speicherplatz 150 MB für Daten für beide; 120 MB für die Indizes der gruppierten Tabelle, 310 MB für die Indizes der nicht gruppierten Tabelle. Dies spiegelt wider, dass der Clustered-Index enger ist als eine RID, und dass der Clustering-Index meistens ein "Werbegeschenk" ist. Wenn die eindeutigen Indizes nicht ID2aktiviert sind, sinkt der erforderliche Indexspeicherplatz für die nicht gruppierte Tabelle auf 155 MB (die Hälfte, wie zu erwarten), für die gruppierte PK jedoch auf nur 150 KB - nahezu nichts.

Ein nicht gruppierter Index eines 32-Bit-Felds in einer gruppierten Tabelle mit einem 32-Bit-Index (nominell insgesamt 64 Bit) nahm also 120 MB in Anspruch, während ein Index eines 32-Bit-Felds in einem Heap mit 64 Bit RID (insgesamt 96 Bit, nominell) nahm 155 MB in Anspruch, etwas weniger als die erwartete Steigerung um 50% von 64-Bit- auf 96-Bit-Schlüssel, aber es gibt natürlich einen Mehraufwand, der den effektiven Größenunterschied verringert.

Das Auffüllen der beiden Tabellen und das Erstellen ihrer Indizes dauerte für jede Tabelle gleich lange. Bei einfachen Tests mit Scans oder Suchvorgängen habe ich keine wesentlichen Leistungsunterschiede zwischen den Tabellen festgestellt, die mit dem Microsoft-Whitepaper übereinstimmen, das von gbn hilfreich verlinkt wurde. Das genannte Papier zeigt einen signifikanten Unterschied für den hochgradig gleichzeitigen Zugriff; Ich bin mir nicht sicher, warum das passiert, hoffentlich jemand mit mehr Erfahrung, als ich mit hochvolumigen OLTP-Systemen sagen kann.

Das Hinzufügen von ~ 40 Bytes zufälliger Daten variabler Länge änderte diese Äquivalenz nicht nennenswert. Das Ersetzen der INTs durch breite UUIDs war ebenfalls nicht der Fall (jede Tabelle wurde in etwa gleichem Maße verlangsamt). Ihr Kilometerstand kann variieren, aber in den meisten Fällen ist es wichtiger, ob ein Index verfügbar ist als welche.

Krimskrams

Um einen Bereichsscan für einen nicht gruppierten Index durchzuführen - entweder weil die Tabelle ein Heap ist oder der Index nicht der gruppierte Index -, müssen Sie den Index scannen und dann für jeden Treffer eine Suche nach der Tabelle durchführen. Dies kann sehr teuer sein, daher ist es manchmal billiger, nur den Tisch zu scannen. Sie können dies jedoch mit einem Deckungsindex umgehen. Dies gilt unabhängig davon, ob Sie Ihre Tabelle geclustert haben oder nicht.

Wie @gbn hervorhob, gibt es keine einfache Möglichkeit, einen Haufen zu komprimieren. Wenn sich Ihre Tabelle jedoch im Laufe der Zeit allmählich vergrößert - ein sehr häufiger Fall -, entsteht wenig Verschwendung, da der durch Löschvorgänge freiwerdende Speicherplatz durch neue Daten gefüllt wird.

Einige der Diskussionen zwischen Heap und gruppierten Tabellen haben ein merkwürdiges Argument von Strawman geliefert, wonach ein Heap ohne Indizes einer gruppierten Tabelle dahingehend unterlegen ist, dass immer ein Tabellenscan erforderlich ist. Dies ist sicherlich richtig, aber der aussagekräftigere Vergleich ist "große gut indizierte Clustertabelle" mit "großer gut indizierter Heap". Wenn Ihre Tabelle sehr klein ist oder Sie immer Tabellenscans durchführen, spielt es keine Rolle, ob Sie sie gruppieren oder nicht.

Da jeder Index in einer Clustered-Tabelle auf den Clustering-Index verweist, werden praktisch alle Indizes abgedeckt. Eine Abfrage, die auf eine indizierte Spalte und die Cluster-Spalte (n) verweist, kann einen Index-Scan ohne Tabellensuche durchführen. Dies ist im Allgemeinen nicht sinnvoll, wenn es sich bei Ihrem Clustering-Index um einen synthetischen Schlüssel handelt. Wenn es sich jedoch um einen Geschäftsschlüssel handelt, den Sie ohnehin abrufen müssen, ist dies eine nette Funktion.

TL; DR

Ich bin ein Data Warehousing-Typ, kein OLTP-Experte. Für Faktentabellen verwende ich fast immer einen Clustering-Index für das Feld, für das meistens Bereichsscans erforderlich sind, normalerweise ein Datumsfeld. Für Dimensionstabellen gruppiere ich sie auf der PK, damit sie für Zusammenführungsverknüpfungen mit Faktentabellen vorsortiert sind.

Es gibt mehrere Gründe, Clustering-Indizes zu verwenden. Wenn jedoch keiner dieser Gründe zutrifft, lohnt sich der Aufwand möglicherweise nicht. Ich vermute, es gibt eine Menge "Wir haben es immer so gemacht" und "es ist nur die beste Praxis", wenn Menschen Clustered-Indizes universell verwenden. Probieren Sie sowohl Ihre Daten als auch Ihre Last aus und sehen Sie, was am besten funktioniert.

Jon aller Berufe
quelle
5

Ich denke, "Die einzige gültige Verwendung ist das Staging von Tabellen, die in Import- / Export- / ETL-Prozessen verwendet werden", um es gelinde auszudrücken, ist ein wenig einschränkend. Sie müssen den erwarteten Anwendungsfall eines bestimmten Systems nehmen und dann basierend auf den Vorzügen von Heaps oder indexorganisierten Tabellen auswählen (ich weiß, ein Oracle-Begriff, aber er beschreibt ihn gut).

Unser Warehouse lädt ca. 1,5 Milliarden Zeilen pro Tag und muss das gleichzeitige Schreiben und Verarbeiten sowie Lesen unterstützen. Der relationale Speicher unterstützt eine OLAP-Datenbank, und daher handelt es sich bei den Lesevorgängen in erster Linie um Tabellenscans. Die Berichte und Downstream-Feeds, die generiert werden, sind im Allgemeinen auch nicht selektiv genug, sodass ein Index nützlich wäre. Das System unterstützt ein Schiebefenster mit Daten. Sobald eine Tabelle geladen ist, schreiben wir selten wieder darauf und da die Implementierung der Tabellenpartitionierung Sch-M-Sperren für Partitionsteilung, Switches und Merges erfordert, werden Sch-S-Sperren für Lesevorgänge usw Das System musste viele Tabellen verwenden, obwohl wir auch einige partitionierte Tabellen haben. Die Verwendung vieler Tabellen erleichtert die Segmentierung von Daten und Bereinigungszyklen, während gleichzeitig Konflikte reduziert werden.

Der zusätzliche Aufwand für eine indexorganisierte Tabelle (gruppierte Tabelle) in einer oder mehreren beliebigen Spalten im Vergleich zu der Möglichkeit, in einen Heap zu gelangen, die OLAP-Partitionen zu verarbeiten, einige Tabellenscanabfragen durchzuführen und diese dann 3 Tage später zu löschen, bedeutet dies ist es einfach nicht wert. Beachten Sie, dass in unserem Fall die Daten von einem großen Grid-Cluster stammen, sodass auch die Daten nicht sortiert werden. Wenn Sie also in eine Tabelle mit einem Clustered-Index einfügen, können andere Probleme auftreten, z. B. "Hotspots" und Seitenteile.

Außerdem finde ich das Argument, dass Seiten verstreut sind, etwas unaufrichtig. Bei gruppierten Indizes können die Seiten auch über die Datei verteilt sein. Es ist nur so, dass nach der Neuindizierung (bei mehr als 1000 Seiten) dies möglicherweise besser ist als ein Haufen, aber Sie mussten auch eine Neuindizierung durchführen.

Wenn dies ein Problem ist, können Sie auch mit Spalten mit geringer Dichte und Komprimierung Speicherplatz sparen. In einigen Fällen kann die Auswahl für eine Tabelle mit einem Clustered-Index zwar schneller sein, Sie müssen dies jedoch mit den Ressourcen abwägen, die zum Laden und Verwalten erforderlich sind.

[Bearbeiten] Ich sollte wahrscheinlich klarstellen, dass nur unsere nicht partitionierten Faktentabellen Haufen sind. Partitionierte Tabellen und Dimensionstabellen verfügen alle über Clustered-Indizes, um effiziente Suchvorgänge usw. zu unterstützen. [Bearbeiten2] Korrigiert: 2,5 bis 1,5 Milliarden. Tut, diese beiden Zahlen liegen nebeneinander. Was passiert, wenn ich auf einem Telefon Antworten eingebe?

Phil Stephenson
quelle