Soll für eine Tabelle mit Identitätsspalte ein gruppierter oder nicht gruppierter PK / eindeutiger Index für die Identitätsspalte erstellt werden?
Der Grund ist, dass andere Indizes für Abfragen erstellt werden. Eine Abfrage, die einen nicht gruppierten Index (auf einem Heap) verwendet und Spalten zurückgibt, die nicht vom Index abgedeckt werden, verwendet weniger logische E / A (LIO), da keine zusätzlichen Suchschritte für den gruppierten Index-B-Tree vorhanden sind.
create table T (
Id int identity(1,1) primary key, -- clustered or non-clustered? (surrogate key, may be used to join another table)
A .... -- A, B, C have mixed data type of int, date, varchar, float, money, ....
B ....
C ....
....)
create index ix_A on T (A)
create index ix_..... -- Many indexes can be created for queries
-- Common query is query on A, B, C, ....
select A, B
from T
where A between @a and @a+5 -- This query will have less LIO if the PK is non-clustered (seek)
select A, B, C
from T
where B between @a and @a+5
....
Clustered PK in Identitätsspalte ist gut, weil:
Sie nimmt eintönig zu, sodass beim Einfügen keine Seitenteile auftreten. Es heißt, eine Masseneinfügung kann so schnell sein wie auf einem Heap-Tisch (nicht gruppiert)
Es ist eng
Werden die Abfragen in der Frage jedoch schneller sein, ohne dass sie gruppiert werden?
** Update: ** Was ist, wenn die Id
FK von anderen Tabellen ist und es in einigen Abfragen verbunden wird?
Antworten:
Standardmäßig ist die PK geclustert und dies ist in den meisten Fällen in Ordnung. Welche Frage sollte jedoch gestellt werden:
PK und Clustered Index sind zwei Unterschiede:
Jetzt haben wir zwei Fragen:
Es kommt darauf an, wie:
Benötigen Sie zunächst einen Clustered-Index? Wenn Sie eine Masseneinfügung durchführen, ist es effizienter, ungeordnete Daten in einem HEAP zu speichern (im Vergleich zu geordneten Daten in einem Cluster). Es verwendet RID (Row Identifier, 8 Bytes), um Zeilen eindeutig zu identifizieren und auf Seiten zu speichern.
Der Clustered-Index sollte kein zufälliger Wert sein. Die Daten auf Blattebene werden gespeichert und nach dem Indexschlüssel sortiert. Daher sollte es kontinuierlich wachsen, um Fragmentierung oder Seitenteilung zu vermeiden. Wenn dies von der PK nicht erreicht werden kann, sollten Sie einen anderen Schlüssel als Clustered Candidate betrachten. Ein gruppierter Index für Identitätsspalten, eine sequenzielle GUID oder sogar das Datum der Einfügung ist aus sequenzieller Sicht in Ordnung, da alle Zeilen der letzten Blattseite hinzugefügt werden. Auf der anderen Seite sollten eindeutige Bezeichner, die für Ihre geschäftlichen Anforderungen als PK nützlich sein können, nicht zu Clustern zusammengefasst werden (sie werden nach dem Zufallsprinzip sortiert / generiert).
Wenn Sie nach einigen Daten- und Abfrageanalysen feststellen, dass Sie zum Abrufen Ihrer Daten meistens denselben Index verwenden, bevor Sie eine Schlüsselsuche in der Cluster-PK durchführen, können Sie ihn als Cluster-Index betrachten, obwohl er Ihre Daten möglicherweise nicht eindeutig identifiziert.
Der gruppierte Indexschlüssel besteht aus allen Spalten, die Sie indizieren möchten. Eine eindeutigere Spalte (4 Byte) wird hinzugefügt, wenn keine eindeutige Einschränkung vorliegt (inkrementeller Wert für Duplikate, andernfalls null). Dieser Indexschlüssel wird dann einmal für jede Zeile auf Blattebene aller nicht gruppierten Indizes gespeichert. Einige von ihnen werden auch mehrmals in Zwischenebenen (Verzweigungen) zwischen der Wurzel- und der Blattebene des Indexbaums (B-Baum) gespeichert. Wenn der Schlüssel zu groß ist, wird der gesamte nicht gruppierte Index größer, benötigt mehr Speicher und mehr E / A, CPU, Speicher, ... Wenn Sie einen PK für Name + Geburtsdatum + Land haben, ist es sehr wahrscheinlich, dass dieser Schlüssel vorhanden ist ist kein guter Kandidat. Es ist zu groß für einen Clustered-Index. Eindeutiger Bezeichner, der NEWSEQUENTIALID () verwendet, wird normalerweise nicht als schmaler Schlüssel (16 Byte) betrachtet, obwohl er sequentiell ist.
Sobald Sie herausgefunden haben, wie Sie Zeilen in Ihrer Tabelle eindeutig identifizieren können, können Sie eine PK hinzufügen. Wenn Sie glauben, dass Sie es in Ihrer Abfrage nicht verwenden werden, erstellen Sie es nicht in Clustern. Sie können immer noch einen anderen nicht gruppierten Index erstellen, wenn Sie ihn irgendwann abfragen müssen. Beachten Sie, dass der PK automatisch einen eindeutigen Index erstellt.
Die nicht gruppierten Indizes enthalten immer den gruppierten Schlüssel. Wenn sich jedoch die indizierten Spalten (+ Schlüsselspalten) decken, wird im Clustered-Index keine Schlüsselsuche durchgeführt. Vergessen Sie nicht, dass Sie einem nicht gruppierten Index auch Include und Where hinzufügen können. (Benutze es weise)
Der Clustered-Index sollte eindeutig und so eng wie möglich sein. Der Clustered-Index sollte sich im Laufe der Zeit nicht ändern und inkrementell eingefügt werden.
Es ist jetzt an der Zeit, SQL zu schreiben, mit dem die Indizes und Einschränkungen für Tabellen, Clustered und Nonclustered erstellt werden.
Dies ist alles theoretisch, da wir Ihr Datenmodell und die verwendeten Datentypen (A und B) nicht kennen.
quelle
Wenn Sie gefragt werden, ob die Standardeinstellung für einen Primärschlüssel in einer Identitätsspalte (insbesondere) nicht gruppiert sein soll, würde ich Nein sagen. Die meisten Tabellen profitieren von einem Clustered-Index. Daher ist es wahrscheinlich insgesamt hilfreich, Clustered als Standard für eine Primärschlüsseleinschränkung festzulegen, insbesondere für neue Benutzer von SQL Server.
Wie bei so ziemlich jeder Option gibt es immer andere Umstände, unter denen einer dem anderen vorzuziehen ist, aber ein erfahrener DBA sollte den Standard kennen und in der Lage sein, ihn bei Bedarf außer Kraft zu setzen. Lesen Sie auch die entsprechenden Fragen und Antworten. Wann sollte ein Primärschlüssel als nicht gruppiert deklariert werden? .
Ja, aber mit Einschränkungen.
RID-Suchvorgänge sind in der Tat effizienter als Schlüsselsuchvorgänge. Selbst wenn sich alle erforderlichen Seiten im Arbeitsspeicher befinden (sehr wahrscheinlich für die oberen Ebenen eines Index), entstehen CPU-Kosten beim Navigieren im gruppierten Index-B-Tree. Infolgedessen kann SQL Server in der Regel viel mehr RID-Suchvorgänge als Schlüsselsuchvorgänge pro CPU-Zeiteinheit ausführen.
Vorbehalte
Das Obige ist oft kein entscheidender Faktor für die Entscheidung, ob eine Tabelle als Heap strukturiert werden soll oder nicht. Es müsste unpraktisch sein, Suchvorgänge (unter Verwendung von Deckungsindizes) zu vermeiden, und die Anzahl der Suchvorgänge müsste groß genug sein, um eine messbare (und wichtige) Auswirkung auf die Leistung in Anbetracht der Hardwareumgebung und der Arbeitslast zu haben.
Es ist nicht wirklich praktisch, in dieser Antwort alle Aspekte der Debatte zwischen Heap und Clustered-Index abzudecken, aber ich möchte sagen, dass es relativ wenige gute Gründe gibt, eine Tabelle generell als Heap zu strukturieren. Für mich würde die Auswahl des in der Frage vorgeschlagenen Designs eine sehr sorgfältige Analyse vor der Implementierung erfordern und eine hohe Messlatte erfüllen müssen. Allgemeine Argumente zur „Skalierbarkeit“ würden nicht ausreichen.
In Bezug auf die Aktualisierung der Frage zu Verknüpfungen wäre es Teil der oben genannten Analyse, die Auswirkungen des Verlusts des Clustered-Index auf Ausführungspläne zu bewerten. Wenn Joins mit verschachtelten Schleifen verwendet werden, ist es sehr praktisch, den Clustered-Index auf dem Join-Schlüssel zu haben, da alle Spalten der Zeile sofort ohne Lookup verfügbar sind.
Nach meiner eigenen Erfahrung ist es sehr oft von Vorteil, eindeutige Clustered-Indizes für Identitätsspalten zu haben. Ich habe Heaps in Bezug auf die Speicherverwaltung als problematisch empfunden, und ich sollte auch erwähnen, dass für einige SQL Server-Features ein eindeutiger Clustered-Index erforderlich ist, um zu funktionieren.
quelle
Tatsächlich müssen weder ein Clustered-Index noch ein Primärschlüssel erstellt werden, da eindeutige Indizes und nicht eindeutige Indizes die Arbeit erledigen können. SQL Server unterstützt seit mindestens Version 1.1 einen Clustered Index, der Primärschlüssel war jedoch nur ein "Konzept", das die Programmierer durch die Definition eines eindeutigen Index erzwangen.
Es scheint jedoch, dass sowohl Primärschlüssel als auch Clustered-Indizes in den meisten Datenbanken wertvolle Konzepte darstellen.
Sehen wir uns die SQL Server-Dokumentation an, um die Teilbeschreibungen einiger Indizierungsoptionen zu sehen, wie unten gezeigt.
Clustered Index: https://msdn.microsoft.com/en-us/library/ms190457.aspx
Primärschlüssel: https://msdn.microsoft.com/en-us/library/ms190457.aspx
Eine Tabelle kann nur eine PRIMARY KEY-Einschränkung enthalten.
Alle in einer PRIMARY KEY-Einschränkung definierten Spalten müssen als NOT NULL definiert sein.
Der Primärschlüssel kann als Clustered-Index (der Standardwert, wenn kein Clustered-Index vorhanden ist) oder als Non-Clustered-Index erstellt werden.
Eindeutiger Index: https://msdn.microsoft.com/en-us/library/ms187019.aspx
Wenn Sie eine UNIQUE-Einschränkung erstellen, wird standardmäßig ein eindeutiger Nonclustered-Index erstellt, um eine UNIQUE-Einschränkung zu erzwingen.
Sie können einen UNIQUE Clustered Index angeben, wenn für die Tabelle noch kein Clustered Index vorhanden ist.
Dies bedeutet, dass Ihre Frage zu Clustered-Indizes und Primärschlüsseln einige der folgenden Punkte betrifft. Bitte beachten Sie, dass nicht jede Tabelle von demselben Indexierungsplan profitiert.
Wann würde ich davon profitieren, wenn der Primärschlüssel vom Clustered Index getrennt wäre?
Möglicherweise, wenn der gruppierte Index breit ist (z. B. 5 Spalten mit Textinformationen, aber der Primärschlüssel klein ist (INT oder BIGINT), wie Sie zu beschreiben scheinen.
Soll der Primärschlüssel allein zum Clustered-Index gemacht werden?
Wenn Sie einen kleinen Primärschlüssel (INT oder BIGINT) haben und es sich um den Clustered Index handelt, ist der Overhead der Clusterspalten relativ gering. Obwohl der geclusterte Primärschlüssel in diesem Fall auch in jedem Index dieser Tabelle vorhanden ist, ist der zu zahlende Preis geringer als bei dem oben diskutierten breiten Cluster.
Dieser Primärschlüssel-Clustered-Index bietet normalerweise keinen einfachen Weg zur seriellen Auswahl vieler Zeilen.
Was ist mit den anderen Spalten, die Sie einst in den Clustered-Index aufnehmen wollten, nachdem Sie einen Clustered-Primärschlüssel erstellt haben ?
Erstellen Sie nach Bedarf einen eindeutigen (oder einen nicht eindeutigen) Index, um diese umfassenden Suchkriterien der Spalten C1, C2, C3, C4, C5 zu indizieren. Die Werte in diesem "Imitation Clustered" -Index können als schnellerer Suchpfad für diese 5 Spalten dienen. Wenn es eine oder zwei nicht indizierte Spalten gibt, die ebenfalls regelmäßig ausgewählt werden, können sie mit in den Index aufgenommen werden
INCLUDE (Doctor_Name, Diagnosis_Synopsis)
.Obwohl ich einfache Clustered-Indizes und Primärschlüssel für nützlich halte, gibt es einige gute Gründe, darüber nachzudenken, ob sie in einer Tabelle oder in einer Datenbank verwendet werden sollen.
Benötigen Sie überhaupt einen Clustered Index?
Wenn Sie Indizes erstellen (eindeutige Indizes und nicht eindeutige Indizes) und den Primärschlüssel definieren, ohne den Aufwand eines Clustered-Index zu verursachen, stellen Sie möglicherweise fest, dass die engeren Indizes Ihnen das bieten, was Sie für Ihre Abfragen benötigen.
Es gibt einige nützliche Verhaltensweisen in Clustered-Indizes und Primärschlüsseln, aber denken Sie daran, dass es wirklich die Indizes sind, die am wichtigsten sind. Entwerfen Sie die Indizierungsstrategie, um die Realitäten Ihrer Anwendung zu berücksichtigen. Möglicherweise
OneBigTable
muss eine andere Indizierungsstrategie verwendet werden als für die meisten Tabellen.Ohne einen Clustered Index werden Ihre Daten als Heap mit dem Row Identifier (RID) gespeichert, was überhaupt kein guter Suchmechanismus ist. Wie bereits erwähnt, können Sie jedoch eindeutige und nicht eindeutige Indizes erstellen, um Ihre Abfragen zu verarbeiten.
Nun kommen Sie zu Heaps:
Heaps und Indizes: https://msdn.microsoft.com/en-us/library/hh213609.aspx
Wenn Sie jedoch auch einige "Hot Spots" in einem großen Datensatz haben, können Sie sich auch einen anderen Indextyp ansehen:
Gefilterter Index: https://msdn.microsoft.com/en-us/library/cc280372.aspx
Ein gut gestalteter gefilterter Index verbessert die Abfrageleistung und die Qualität des Ausführungsplans, da er kleiner als ein nicht gruppierter Ganztabellenindex ist und gefilterte Statistiken enthält. Die gefilterten Statistiken sind genauer als die vollständigen Tabellenstatistiken, da sie nur die Zeilen im gefilterten Index abdecken .
Bei gefilterten Indizes gibt es eine Reihe von Einschränkungen, die im Link zu gefilterten Indizes aufgeführt sind.
Allerdings , wenn Sie im Denken über diese Möglichkeit des Überspringens von Primärschlüsseln und Clustered - Indizes insgesamt interessiert sind, können Sie Markus Winand der Post verbunden unten lesen. Mit einigen Codebeispielen demonstriert er seine Gründe dafür, dass es manchmal eine gute Idee sein könnte, auf die Verwendung dieser Funktionen zu verzichten.
http://use-the-index-luke.com/blog/2014-01/unreasonable-defaults-primary-key-clustering-key
Aber es kommt alles wieder darauf an, Ihre Anwendung zu verstehen und den Code, die Tabellen, die Indizes usw. so zu gestalten, dass sie zu dem Job passen, den Sie gerade ausführen.
quelle
Ein paar Punkte zu beachten.
Ein Index (gruppiert oder nicht) mit einem monoton ansteigenden Wert erspart Ihnen Seitenteile bei Masseneinfügungen, erstellt jedoch einen neuen Hotspot am hinteren Ende des Index. Auch wenn dies bei einer Masseneinfügung mit einem einzelnen Thread kein Problem darstellt, erhöht dies definitiv die Konkurrenz für eine Multithread-Anwendung, bei der neue Tupel mit einer hohen Rate eingefügt werden, da die Threads ständig um den Zugriff auf die letzte Seite des Index konkurrieren.
Das Clustering der Tabelle basierend auf einer Ersatz-PK (Identitäts-PK) ist selten vorteilhaft. Ein solcher Primärschlüssel wird meist verwendet, um entweder einzeln auf Tupel zuzugreifen oder den gesamten Index nach Joins zu durchsuchen. In beiden Fällen spielt es keine Rolle, ob der Index geclustert ist oder nicht (mit Ausnahme von Merge-Joins, kann es sein, aber wie häufig sind sie?)
Ich denke, dass Sie am meisten von einem Clustered-Index profitieren, der Abfragen abdeckt, die nach einem Schlüsselbereichsscan fragen, und zusätzliche Prädikate, die auf andere Spalten verweisen.
quelle