2009-09-17 14 views
9

In letzter Zeit habe ich etwas über Indizes aller Typen gelesen und der wichtigste Rat ist, den geclusterten Index auf den Primärschlüssel der Tabelle zu setzen, aber was ist, wenn der Primärschlüssel tatsächlich nicht in einer Abfrage verwendet wird (über eine Auswahl oder beitreten) und wird nur für rein relationale Zwecke verwendet, so dass in diesem Fall nicht angezweifelt wird. Beispiel, ich habe eine car_parts Tabelle und sie enthält 3 Spalten, car_part_id, car_part_no und car_part_title. car_part_id ist die eindeutige Primärschlüsselidentitätsspalte. In diesem Fall ist car_part_no auch einzigartig und ist am wahrscheinlichsten car_part_title. car_part_no wird am meisten abgefragt, macht es also keinen Sinn, den Clustered-Index auf diese Spalte zu setzen anstatt car_part_id? Die Grundlagen der Frage ist, welche Spalte eigentlich den gruppierten Index haben sollte, da Sie nur einen von ihnen haben dürfen?In welche Spalte soll der Clustered-Index gesetzt werden?

+1

Es ist sehr gut, dass Sie sich solche Fragen stellen. Die richtige Wahl hat jetzt einen großen Einfluss auf Ihre Leistung und Skalierbarkeit. –

+0

Die meisten Primärschlüssel, die "rein für relationale Zwecke" da sind, spiegeln eine falsche Vorstellung vom relationalen Modell wider. Wenn keine Fremdschlüssel auf einen Primärschlüssel verweisen, ist die Wahrscheinlichkeit groß, dass ein relationales Modell einen anderen Primärschlüssel gewählt hätte. –

Antwort

8

Ein Index, gruppiert oder nicht geklammert, kann vom Abfrageoptimierer genau dann verwendet werden, wenn der Schlüssel ganz links im Index gefiltert wird. Wenn Sie also einen Index für Spalten (A, B, C) definieren, wird eine WHERE-Bedingung an [email protected], an [email protected] oder an [email protected] AND [email protected] den Index nicht vollständig nutzen (siehe Hinweis). Dies gilt auch für Join-Bedingungen.Jeder WHERE-Filter, der A enthält, berücksichtigt den Index: [email protected] oder [email protected] AND [email protected] oder [email protected] AND [email protected] oder [email protected] AND [email protected] AND [email protected].

in Ihrem Beispiel Also, wenn Sie den clustred Index machen auf part_no als die linke Taste, dann wird eine Abfrage für ein bestimmtes part_id sucht, wird nicht den Index verwenden und ein separater nicht gruppierten Index auf part-id vorhanden sein muss.

Nun zu der Frage, welche der vielen Indizes sollte die Cluster eins sein. Wenn Sie mehrere Abfragemuster haben, die etwa die gleiche Bedeutung und Frequenz sind und sich gegenseitig über die Bedingungen der Schlüssel widersprechen benötigt (zB häufige Abfragen von entwederpart_no oder part_id.), Dann nehmen Sie andere Faktoren in Betracht:

  • Breite: Der Clustered-Indexschlüssel wird von alle andere nicht geclusterten Indizes als Suchschlüssel verwendet. Wenn Sie also einen breiten Schlüssel wählen (sagen wir zwei Uniquentifier-Spalten), dann machen Sie alle anderen Indizes breiter, verbrauchen also mehr Platz, erzeugen mehr IO und verlangsamen alles. Wählen Sie also zwischen den gleichwertigen Schlüsseln aus Sicht des Lesens die schmalste als gruppiert und die breiteren als nicht gruppiert.
  • contention: Wenn Sie bestimmte Muster von Einfügen und Löschen haben, versuchen Sie, sie physisch zu trennen, so dass sie in verschiedenen Teilen des gruppierten Index auftreten. Z.B. Wenn die Tabelle als eine Warteschlange mit allen Einfügungen an einem logischen Ende und allen Löschungen am anderen logischen Ende fungiert, versuchen Sie, den gruppierten Index so zu gestalten, dass die physische Reihenfolge mit dieser logischen Reihenfolge übereinstimmt (z. B. Reihenfolge der Enqueues).
  • Partitionierung: Wenn die Tabelle sehr groß ist und Sie Partioning bereitstellen möchten, muss der Partitionierungsschlüssel der Clustered-Index sein. Ein typisches Beispiel sind historische Daten, die mithilfe eines gleitenden Fensterpartitionierungsschemas archiviert werden. Selbst wenn die Entitäten einen logischen Primärschlüssel wie "entity_id" haben, wird der clustred Index von einer datetime-Spalte ausgeführt, die auch für die Partitionierungsfunktion verwendet wird.
  • Stabilität: ein Schlüssel, der häufig ändert, ist ein schlechter Kandidat für einen gruppierten Schlüssel als jede Aktualisierung des gruppierte Schlüsselwert und Kraft all nicht gruppierte Indizes auf den Nachschlag-Schlüssel speichern sie zu aktualisieren. Da eine Aktualisierung eines gruppierten Schlüssels den Datensatz wahrscheinlich auch auf eine andere Seite verschiebt, kann dies zu einer Fragmentierung des gruppierten Index führen.

Hinweis: nicht voll Hebelwirkung, da manchmal der Motor einen nicht gruppierten Index zu Scan statt des gruppierten Index einfach wählen, weil schmaler und damit weniger Seiten zu scannen hat. In meinem Beispiel, wenn Sie einen Index auf (A, B, C) und einen WHERE-Filter auf [email protected] und die Abfrage Projekte C haben, wird der Index wahrscheinlich verwendet werden, aber nicht als eine Suche, wie ein Scan, weil immer noch schneller als ein vollständiger gruppierter Scan (weniger Seiten).

1

Der Clustered-Index sollte in der Spalte stehen, die am häufigsten abgefragt wird. Dies schließt Joins ein, da ein Join wie eine direkte Abfrage auf die Tabelle zugreifen und die angegebenen Zeilen finden muss.

Sie können Ihre Indizes später jederzeit neu erstellen, wenn sich Ihre Anwendung ändert und Sie feststellen, dass Sie eine Tabelle mit einer anderen Indexstruktur optimieren müssen.

Einige zusätzliche Richtlinien für die Entscheidung, worauf Sie Ihre Tabelle aufsetzen sollten, finden Sie auf MSDN hier: Clustered Index Design Guidelines.

+0

also würde ich davon ausgehen, dass mein Beitrag dann sinnvoll ist. Wenn ein innerer Join für den Primärschlüssel verwendet wird, wird er als Abfrage für die Spalte gezählt, auch wenn er nicht in der Auswahlliste enthalten ist. – Xaisoft

+0

... daran erinnernd, dass die Abfrage nicht notwendigerweise bedeutet, dass sie vom Endbenutzer bei ihren Suchen als Kriterium verwendet wird, sondern auch in JOINs und verschiedenen [implizierten/vergessenen] Unterabfragen verwendet wird. – mjv

+0

@mjv, du liest meine Gedanken. – Xaisoft

2

Beachten Sie die Nutzungsmuster; Wenn Sie fast immer die DB auf dem car_part_no abfragen, wäre es wahrscheinlich vorteilhaft, wenn sie in dieser Spalte geclustert wäre.

Vergessen Sie jedoch nicht Joins; Wenn Sie sich am häufigsten der Tabelle anschließen und der Join das Feld "car_part_id" verwendet, haben Sie einen guten Grund, den Cluster bei "car_part_id" zu belassen.

Noch etwas zu beachten (weniger in diesem Fall, aber im Allgemeinen bei der Berücksichtigung von Clustered-Indizes) ist, dass der Clustered-Index implizit in jedem anderen Index auf der Tabelle erscheint; Wenn Sie zum Beispiel car_part_title indexieren, enthält dieser Index implizit auch die car_part_id. Dies kann sich darauf auswirken, ob ein Index eine Abfrage abdeckt oder nicht, und auch, wie viel Speicherplatz der Index belegen wird (was sich auf die Speicherauslastung usw. auswirkt).

4

Clustered-Indizes sind gut, wenn Sie Datenbereiche abfragen. Beispiel:

SELECT * FROM theTable WHERE age BETWEEN 10 AND 20 

Der gruppierte Index ordnet Zeilen in der bestimmten Reihenfolge auf Ihrer Computerdiskette an. Deshalb Reihen mit dem Alter = 10 werden nebeneinander sein, und nach ihnen wird es Zeilen mit dem Alter = 11, usw.

Wenn Sie genau auswählen, wie folgt aus:

SELECT * FROM theTable WHERE age = 20 

die nicht -clustered Index ist auch gut. Es ordnet Daten auf Ihrer Computerdiskette nicht neu an, aber es erstellt spezielle Struktur mit einem Zeiger auf den Zeilen, die Sie benötigen.

Es hängt also stark von der Art der Abfragen ab, die Sie ausführen.

4

Kimberly Tripp ist immer eine der besten Quellen für Einblicke in die Indizierung.

Siehe ihren Blog-Eintrag "Ever-increasing clustering key - the Clustered Index Debate - again!", in dem sie ganz klar auflistet und erläutern die wichtigsten Anforderungen an einen guten Clustering-Schlüssel - es muss sein:

  • Einzigartige
  • Narrow
  • Static

und am besten von allen, wenn Sie verwalten können:

  • ständig wachsenden

all dies unter Berücksichtigung, ein INT IDENTITY (oder BIGINT IDENTITY wenn Sie wirklich brauchen mehr als 2 Milliarden Zeilen) ausarbeitet die beste Wahl in der überwiegenden Mehrzahl der Fälle zu sein.

Eine Sache, die viele Leute nicht realisieren (und daher bei ihrer Wahl nicht berücksichtigen), ist die Tatsache, dass der Clustering-Schlüssel (alle Spalten, aus denen der Clustered-Index besteht) hinzugefügt wird jeden einzelnen Indexeintrag für jeden nicht gruppierten Index auf Ihrer Tabelle - daher wird die "enge" Anforderung besonders wichtig!

Da der Clustering-Schlüssel für Lesezeichen-Lookups verwendet wird (Nachschlagen der tatsächlichen Datenzeile, wenn eine Zeile in einem nicht gruppierten Index gefunden wird), wird auch die "eindeutige" Anforderung sehr wichtig. So wichtig in der Tat, dass, wenn Sie eine (Menge von) Spalte (n) wählen, die garantiert/eindeutig ist, SQL Server wird eine 4-Byte-Uniquefier zu jeder Zeile hinzufügen -> so machen Sie jede Ihrer Clustered-Index-Schlüssel extra breit; definitiv keine gute Sache.

Marc

Verwandte Themen