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.
sql-server
clustered-index
heap
marc.d
quelle
quelle
Antworten:
Die einzig gültigen Verwendungen sind für
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:
Siehe auch
quelle
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 BitBIGINT
) oder größer (48 BitDATETIME2()
plus 32 Bit) seinINT
kann. oder eine 128-Bit-GUID). Offensichtlich führt eine breitere Referenz zu größeren und teureren Indizes.Platzanforderungen
Mit diesen beiden Tabellen:
... 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
ID2
aktiviert 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
INT
s 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.
quelle
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?
quelle