Ja, es gibt absolut negative Konsequenzen für die Verwendung einer Zeichenfolge anstelle eines numerischen Typs für einen Primärschlüssel, und dies umso mehr, wenn diese PK geclustert ist (was in Ihrem Fall tatsächlich der Fall ist). Der Grad, in dem Sie die Auswirkung (en) der Verwendung eines Zeichenfolgenfelds sehen, hängt jedoch davon ab, a) wie viele Zeilen sich in dieser Tabelle befinden und b) wie viele Zeilen in anderen Tabellen für diese PK mit einem Fremdschlüssel versehen sind. Wenn Sie nur 10.000 Zeilen in dieser Tabelle und 100.000 Zeilen in einigen anderen Tabellen haben, die über dieses Feld an diese Tabelle weitergeleitet werden, ist dies möglicherweise nicht so auffällig. Aber diese Effekte werden mit zunehmender Anzahl der Zeilen sicherlich deutlicher.
Sie müssen berücksichtigen, dass die Felder in einem Clustered-Index auf Nicht-Clustered-Indizes übertragen werden. Sie betrachten also nicht nur bis zu 40 Bytes pro Zeile, sondern (40 * some_number) Bytes. Und in allen FK-Tabellen haben Sie dieselben 40 Bytes in der Zeile. In den meisten Fällen gibt es einen nicht gruppierten Index für dieses Feld, wie er in JOINs verwendet wird. In allen Tabellen, in denen FK verwendet wird, wird er jetzt wirklich verdoppelt dieses. Wenn man denkt, dass 40 Bytes * 1 Million Zeilen * 10 Kopien davon kein Grund zur Sorge sind, lesen Sie bitte meinen Artikel Disk Is Cheap! ORLY? Darin werden alle (oder zumindest die meisten) Bereiche aufgeführt, die von dieser Entscheidung betroffen sind.
Die andere zu berücksichtigende Sache ist, dass das Filtern und Sortieren nach Zeichenfolgen, insbesondere wenn keine binäre Kollatierung verwendet wird (ich gehe davon aus, dass Sie den Datenbankstandard verwenden, bei dem die Groß- und Kleinschreibung normalerweise nicht berücksichtigt wird), weitaus weniger effizient ist (dh länger dauert) als bei Verwendung von INT
/ BIGINT
. Dies wirkt sich auf alle Abfragen aus, die in diesem Feld gefiltert / verknüpft / sortiert werden.
Daher CHAR(5)
wäre die Verwendung von so etwas für eine Clustered PK wahrscheinlich in Ordnung, aber meistens, wenn es auch mit COLLATE Latin1_General_100_BIN2
(oder so ähnlich) definiert wurde.
Und kann sich der Wert von [CODE]
jemals ändern? Wenn ja, dann ist das noch mehr Grund, es nicht als PK zu verwenden (selbst wenn Sie die FKs auf setzen ON UPDATE CASCADE
). Wenn es sich nicht ändern kann oder wird, ist das in Ordnung, aber es gibt bereits mehr als genug Gründe, es nicht als Clustered PK zu verwenden.
Natürlich könnte die Frage falsch formuliert sein, da es den Anschein hat, dass Sie dieses Feld derzeit bereits in Ihrer PK haben.
Unabhängig davon ist es bei weitem die beste Option, [ID_CODE]
als Clustered PK zu verwenden, dieses Feld in verwandten Tabellen als FK zu verwenden und [CODE]
als zu behalten UNIQUE INDEX
(was bedeutet, dass es sich um einen "alternativen Schlüssel" handelt).
Update
Ein bisschen mehr Infos basierend auf dieser Frage in einem Kommentar zu dieser Antwort:
Ist [ID_CODE] als PRIMARY KEY die beste Option, wenn ich die Spalte [CODE] zum Nachschlagen der Tabelle verwende?
Dies alles hängt von sehr vielen Faktoren ab, von denen ich einige bereits erwähnt habe, aber noch einmal wiederholen werde:
Ein Primärschlüssel gibt an, wie die einzelne Zeile identifiziert wird, unabhängig davon, ob sie von einem Fremdschlüssel referenziert wird oder nicht. Wie Ihr System die Zeile intern identifiziert, hängt damit zusammen, aber nicht unbedingt mit der Art und Weise, wie Ihre Benutzer sich selbst / diese Zeile identifizieren. Jede NOT NULL-Spalte mit eindeutigen Daten könnte funktionieren, es sind jedoch praktische Aspekte zu berücksichtigen, insbesondere wenn die PK tatsächlich von FKs referenziert wird. Zum Beispiel sind GUIDs einzigartig und einige Leute verwenden sie aus verschiedenen Gründen sehr gerne, aber sie sind ziemlich schlecht für Clustered-Indizes ( NEWSEQUENTIALID
ist besser, aber nicht perfekt). Auf der anderen Seite sind GUIDs als alternative Schlüssel in Ordnung und werden von der App zum Nachschlagen der Zeile verwendet. Die JOINs werden jedoch weiterhin mit einer INT-PK (oder einer ähnlichen PK) ausgeführt.
Bisher haben Sie uns nicht gesagt, wie das [CODE]
Feld aus allen Blickwinkeln in das System passt, außer jetzt zu erwähnen, dass Sie auf diese Weise Zeilen nachschlagen, aber ist das für alle Abfragen oder nur für einige? Daher:
Zum [CODE]
Wert:
- Wie wird es erzeugt?
- Ist es inkrementell oder pseudozufällig?
- Ist es eine einheitliche Länge oder eine unterschiedliche Länge?
- Welche Zeichen werden verwendet?
- Wenn Sie alphabetische Zeichen verwenden: Wird zwischen Groß- und Kleinschreibung unterschieden oder nicht?
- Kann es sich nach dem Einfügen jemals ändern?
Zu dieser Tabelle:
- Haben andere Tabellen FK zu dieser Tabelle? Oder werden diese Felder (
[CODE]
oder [ID_CODE]
) in anderen Tabellen verwendet, auch wenn sie nicht explizit mit Fremdschlüssel versehen sind?
- Wenn
[CODE]
das einzige Feld zum Abrufen einzelner Zeilen verwendet wird, welchen Zweck erfüllt das [ID_CODE]
Feld dann? Wenn es nicht verwendet wird, warum sollte es überhaupt verwendet werden (was von der Antwort auf "Kann sich das [CODE]
Feld jemals ändern?" Hängt )?
- Wie viele Zeilen in dieser Tabelle?
- Wenn andere Tabellen auf diese Tabelle verweisen, wie viele und wie viele Zeilen in jeder von ihnen?
- Was sind die Indizes für diese Tabelle?
Diese Entscheidung kann nicht nur über die Frage "NVARCHAR ja oder nein?" Ich werde noch einmal sagen, dass ich es im Allgemeinen nicht für eine gute Idee halte, aber es gibt sicherlich Zeiten, in denen es in Ordnung ist. Bei so wenigen Feldern in dieser Tabelle ist es unwahrscheinlich, dass es mehr oder zumindest nicht viele Indizes gibt. In beiden [CODE]
Fällen kann es also in Ordnung sein, den Clustered-Index zu verwenden. Und wenn keine anderen Tabellen auf diese Tabelle verweisen, ist es möglicherweise auch in Ordnung, sie zur PK zu machen. Wenn jedoch andere Tabellen auf diese Tabelle verweisen, würde ich mich für das [ID_CODE]
Feld als PK entscheiden, selbst wenn es nicht gruppiert ist.