Sì, ci sono assolutamente conseguenze negative sull'uso di una stringa anziché di un tipo numerico per una chiave primaria, e ancora di più se quel PK è cluster (cosa che in effetti è nel tuo caso). Tuttavia, il grado in cui vedi l'effetto (i) dell'uso di un campo stringa è una funzione di a) quante righe sono in questa tabella eb) quante righe in altre tabelle sono con chiave esterna a questo PK. Se hai solo 10k righe in questa tabella e 100k righe in poche altre tabelle che vengono indirizzate a questa tabella tramite quel campo, forse non sarà così evidente. Ma questi effetti diventano certamente più evidenti all'aumentare del numero di righe.
È necessario considerare che i campi in un indice cluster vengono trasferiti in indici non cluster. Quindi non stai solo guardando fino a 40 byte per riga, ma (40 * un certo numero) byte. E in tutte le tabelle FK hai gli stessi 40 byte nella riga più il più delle volte ci sarà un indice non cluster su quel campo come viene utilizzato nei JOIN, quindi ora è davvero raddoppiato in tutte le tabelle che FK questo. Se si è inclini a pensare che 40 byte * 1 milione di righe * 10 copie di esso non siano nulla di cui preoccuparsi, consultare il mio articolo Disk Is Cheap! ORLY? che descrive in dettaglio (o almeno la maggior parte) delle aree interessate dalla presente decisione.
L'altra cosa da considerare è che il filtraggio e l'ordinamento su stringhe, specialmente quando non si utilizza un confronto binario (suppongo che si stia utilizzando l'impostazione predefinita del database che in genere non fa distinzione tra maiuscole e minuscole) è molto meno efficiente (ovvero richiede più tempo) rispetto a quando si utilizza INT
/ BIGINT
. Ciò influisce su tutte le query che filtrano / uniscono / ordinano su questo campo.
Quindi, usare qualcosa del genere CHAR(5)
sarebbe probabilmente OK per un PK in cluster, ma soprattutto se fosse anche definito con COLLATE Latin1_General_100_BIN2
(o qualcosa del genere).
E il valore di [CODE]
mai cambiare? Se sì, questo è un motivo in più per non usarlo come PK (anche se si impostano gli FK su ON UPDATE CASCADE
). Se non può o non cambierà mai, va bene, ma ci sono ancora ragioni più che sufficienti per non usarlo come PK in cluster.
Naturalmente, la domanda potrebbe essere formulata in modo errato in quanto sembra che tu abbia già questo campo nel tuo PK.
Indipendentemente da ciò, l'opzione migliore, di gran lunga, è utilizzare [ID_CODE]
come PK in cluster, utilizzare quel campo in tabelle correlate come FK e mantenere [CODE]
come un UNIQUE INDEX
(che significa che è una "chiave alternativa").
Aggiorna Altre
informazioni basate su questa domanda in un commento su questa risposta:
[ID_CODE], come PRIMARY KEY, è l'opzione migliore se utilizzo la colonna [CODICE] per cercare la tabella?
Tutto dipende da moltissimi fattori, alcuni dei quali ho già menzionato ma ribadirò:
Una chiave primaria è il modo in cui viene identificata la singola riga, indipendentemente dal fatto che sia referenziata o meno da qualsiasi chiave esterna. Il modo in cui il sistema identifica internamente la riga è correlato, ma non necessariamente lo stesso, al modo in cui gli utenti identificano se stessi / quella riga. Qualsiasi colonna NOT NULL con dati univoci potrebbe funzionare, ma ci sono problemi di praticità da considerare, specialmente se il PK è, di fatto, referenziato da qualsiasi FK. Ad esempio, i GUID sono unici e ad alcune persone piace molto usarli per vari motivi, ma sono piuttosto dannosi per gli indici cluster ( NEWSEQUENTIALID
è meglio, ma non perfetto). D'altra parte, i GUID vanno bene come tasti alternativi e vengono utilizzati dall'app per cercare la riga, ma i JOIN vengono comunque eseguiti utilizzando un PK INT (o simile).
Finora non ci hai detto come il [CODE]
campo si adatta al sistema da tutte le angolazioni, al di fuori di ora menzionando che è così che cerchi le righe, ma lo è per tutte le domande o solo alcune? Quindi:
Questa decisione non può essere presa esclusivamente sulla questione "NVARCHAR sì o no?". Dirò di nuovo che in generale non trovo che sia una buona idea, ma ci sono certamente momenti in cui va bene. Dati così pochi campi in questa tabella, è improbabile che ci siano altri o almeno non molti indici. Quindi potresti andare bene in entrambi i modi [CODE]
come indice cluster. E se nessun'altra tabella fa riferimento a questa tabella, potresti anche andare bene trasformandola in PK. Ma, se altre tabelle fanno riferimento a questa tabella, opterei per il [ID_CODE]
campo come PK, anche se non cluster.