Frage

Wenn ich eine Tabelle mit den Spalten habe:

  • Künstler
  • Album
  • Lied
  • NumberOfListens

... ist es besser, einen gruppierten Primärschlüssel auf Künstler, Album zu setzen und Song oder eine selbstinkrementierende id-Spalte haben und eine eindeutige Einschränkung auf Künstler, Album setzen und Song.

Wie wichtig ist die Konsistenz der Datenbank? Wenn die Hälfte meiner Tabellen haben Primärschlüssel geclustert und die andere Hälfte eine ID-Spalte mit einzigartigen Einschränkungen, das ist schlecht oder tut es Angelegenheit nicht? Beide Wege scheinen mir gleich, aber ich weiß nicht, was der Industriestandard ist oder welche besser ist und warum.

War es hilfreich?

Lösung

Sie müssen wirklich zwei Fragen auseinander halten:

1) Primärschlüssel ist ein logisches Konstrukt - eine des Kandidaten-Schlüssels, der eindeutig und zuverlässig jede Zeile in der Tabelle zeigt. Das kann alles, wirklich sein - ein INT, eine GUID, ein String - wählen, was am meisten Sinn für Ihr Szenario macht. Sie verweisen auf Primärschlüssel in Ihren Fremdschlüssel-Constraints, so die für die Integrität Ihrer Datenbank entscheidend sind. Benutzen Sie sie - immer -. Zeitraum

2) der Clustering-Schlüssel (die Spalt oder Spalten, die den "Clustered-Index" auf dem Tisch zu definieren) - das ist eine physische Speicherbezogene Sache, und hier , ein kleines, einzigartige, stabil, ständig wachsender Datentyp ist die beste Wahl - INT oder BIGINT als Standard-Option.

In der Standardeinstellung ist der Primärschlüssel auf einer SQL Server-Tabelle auch als Gruppierungsschlüssel verwendet - aber das muss nicht so sein, können Sie einfach eine Spalte auswählen, das nicht Ihre primären Schlüssel sind, Ihr Clustering-Schlüssel zu sein .

Dann gibt es noch ein anderes Problem zu betrachten: der Clustering-Schlüssel auf einem Tisch zu jedem hinzugefügt und jedem Eintrag auf jedem Nicht-Clustered-Index auf dem Tisch als auch - also wirklich machen wollen Sie sicher, es ist so klein wie möglich . und im Vergleich zu einem VARCHAR (20) oder um die Clustering-Schlüssel, können Sie sich Hunderte von Megabytes Speicherplatz auf der Festplatte speichern und in Serverspeicher - in der Regel ein INT mit 2+ Milliarden Zeilen sollten für die überwiegende Mehrheit der Tabellen ausreichend sein.

Einige mehr Stoff zum Nachdenken - ausgezeichnetes Material von Kimberly Tripp - lesen Sie es, lesen Sie es noch einmal, verdauen es! Es ist das SQL Server Indizierung Evangelium, wirklich.

Marc

Andere Tipps

Künstler, Album und Song:

Ich würde nie einen Primärschlüssel auf Spalten von langen Text wie setzen. Verwenden Sie eine Autoinkrement-ID, die das Cluster-PK ist. Wenn Sie die Künstler wollen, Album und Song, einzigartig zu sein, ad ein eindeutigen Index für die drei. Wenn Sie mit dem Album oder Song, unabhängig von unabhängigen Künstler suchen möchten, müssen Sie einen Index für jeden, müssen die in der PK zieht, so eine kleine PK aufeinander Index spart haben. Die Einsparungen sind nicht nur Speicherplatz, sondern im Speicher-Cache und mehr Tasten auf einer Seite.

Clustered-Indizes sind für Bereich basierte Abfragen. Zum Beispiel kann ein Protokoll Datum oder Bestelldatum. Putting eine auf Künstler, Album und Song wird [wahrscheinlich] Ursache Fragmentierung beim Einfügen von neuen Zeilen.

Wenn Ihre DB unterstützt, fügen Sie einen nicht gruppierten Primärschlüssel für Künstler, Album und Song und nennt es gut. Oder fügen Sie einfach einen eindeutigen Schlüssel auf Künstler, Album und Song.

würde einen selbstinkrementierende Primärschlüssel, der nur wirklich nützlich sein, wenn Sie die referentielle Integrität zu einem anderen Tisch mußten haben.

Ohne die genaue Anforderungen zu kennen, in der Regel würden Sie wahrscheinlich einen Künstler Tisch haben, und möglicherweise auch Album-Tabelle. Ein Song Tabelle würde dann eine einzigartige Kombination von Künstler-ID, Album-ID und dann Lied sein. Ich würde die Einzigartigkeit durch einen Index oder Zwang durchzusetzen, je nach Anwendung, und verwenden Sie eine ID für einen Primärschlüssel.

Zunächst einmal ist es schon ein Problem hier, weil die Daten nicht normalisiert. Erstellen von jeder Art von Index auf einer Reihe von Textspalten ist etwas, das, wann immer möglich, vermieden werden sollte. Auch wenn diese Spalten sind nicht Text (und ich vermute, dass sie sind), es immer noch keinen Sinn, Künstler, Album haben und Lied in der gleichen Tabelle. A viel besseres Design für diese wäre:

Artists (
    ArtistID int NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
    ArtistName varchar(100) NOT NULL)

Albums (
    AlbumID int NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
    ArtistID int NOT NULL,
    AlbumName varchar(100) NOT NULL,
    CONSTRAINT FK_Albums_Artists FOREIGN KEY (ArtistID)
        REFERENCES Artists (ArtistID))

Songs (
    SongID int NOT NULL IDENTITY(1, 1) PRIMARY KEY CLUSTERED,
    AlbumID int NOT NULL,
    SongName varchar(100) NOT NULL,
    NumberOfListens int NOT NULL DEFAULT 0
    CONSTRAINT FK_Songs_Albums FOREIGN KEY (AlbumID)
        REFERENCES Albums (AlbumID))

Wenn Sie diesen Entwurf haben, haben Sie die Möglichkeit für individuelle Alben und Künstler sowie Songs zu suchen. Sie können auch hinzufügen, Indizes abdecken Abfragen zu beschleunigen, und die Indizes werden viel kleiner und damit schneller als der ursprüngliche Entwurf.

Wenn Sie keine Bereichsabfragen tun müssen, um (die Sie wahrscheinlich nicht), dann könnte man die IDENTITY Schlüssel mit einem ROWGUID ersetzen, wenn das passt Ihr Design besser; ist es nicht wirklich viel aus in diesem Fall würde ich mit dem einfachen IDENTITY bleiben.

Sie haben mit Clustering Schlüssel vorsichtig sein. Wenn Sie auf einer Tastengruppe, die vollständig nicht einmal entfernt sequentielle (und einen Künstler, Album und Song-Namen auf jeden Fall als nicht-sequenzielle qualifizieren), dann am Ende mit Seitenteilungen und anderen Gemeinheiten auf. Sie will das nicht. Und wie Marc sagt, wird für jeden Index eine Kopie dieser Schlüssel hinzugefügt und Sie auf jeden Fall nicht will, dies bei Ihrem Schlüssel 300 oder 600 Bytes lang.

Wenn Sie zu schnell Abfrage für die Anzahl der Streams für einen bestimmten Song vom Künstler, Album und Songtitel in der Lage sein wollen, ist es mit der obigen Konstruktion ist eigentlich ganz einfach ist, den Sie indizieren müssen nur richtig:

CREATE UNIQUE INDEX IX_Artists_Name ON Artists (ArtistName)
CREATE UNIQUE INDEX IX_Albums_Artist_Name ON Albums (ArtistID, AlbumName)
CREATE UNIQUE INDEX IX_Songs_Album_Name ON Songs (AlbumID, SongName)
    INCLUDE (NumberOfListens)

Nun ist diese Abfrage wird schnell:

SELECT ArtistName, AlbumName, SongName, NumberOfListens
FROM Artists ar
INNER JOIN Albums al
    ON al.ArtistID = ar.ArtistID
INNER JOIN Songs s
    ON s.AlbumID = al.AlbumID
WHERE ar.ArtistName = @ArtistName
AND al.AlbumName = @AlbumName
AND s.SongName = @SongName

Wenn Sie den Ausführungsplan überprüfen Sie werden sehen, 3 Index sucht - es ist so schnell, wie Sie es bekommen kann. Wir haben genau die gleiche Einzigartigkeit wie im ursprünglichen Design garantiert und auf Geschwindigkeit optimiert. sowohl was noch wichtiger ist, es normalisiert, so ein Künstler und ein Album, ihre eigenen spezifischen Identität haben, die dies sehr viel einfacher macht, die langfristige Verwaltung über. Es ist viel einfacher für „alle Alben von Künstlern X.“ suchen Es ist viel viel einfacher und schneller suchen "alle Titel auf dem Album Y."

Wenn Sie eine Datenbank entwerfen, Normalisierung Ihre erste Sorge sein sollte, sollte die Indizierung Ihre Sekunde. Und sind Sie wahrscheinlich, dass zu finden, wenn Sie ein normalisierte Design haben, die beste Indexstrategie Art offensichtlich wird.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top