Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

Devo progettare una tabella con una chiave primaria di varchar o int?

Quando si sceglie la chiave primaria di solito si sceglie anche la chiave cluster. I due sono spesso confusi, ma devi capire la differenza.

Chiavi primarie sono affari logici elementi. La chiave primaria viene utilizzata dall'applicazione per identificare un'entità e la discussione sulle chiavi primarie riguarda in gran parte l'utilizzo di chiavi naturali o di chiavi surrogate. I collegamenti vanno molto più in dettaglio, ma l'idea di base è che le chiavi naturali sono derivate da una proprietà di entità esistente come ssn o phone number , mentre le chiavi surrogate non hanno alcun significato per quanto riguarda l'entità aziendale, come id o rowid e di solito sono di tipo IDENTITY o una sorta di uuid. La mia opinione personale è che le chiavi surrogate siano superiori alle chiavi naturali e la scelta dovrebbe essere sempre valori di identità per applicazioni solo locali, guide per qualsiasi tipo di dato distribuito. Una chiave primaria non cambia mai durante la vita dell'entità.

Chiavi raggruppate sono la chiave che definisce la memorizzazione fisica delle righe nella tabella. La maggior parte delle volte si sovrappongono alla chiave primaria (l'identificatore di entità logica), ma ciò non è effettivamente imposto né richiesto. Quando i due sono diversi significa che nella tabella è presente un indice univoco non cluster che implementa la chiave primaria. I valori delle chiavi raggruppati possono effettivamente cambiare durante la durata della riga, con il risultato che la riga viene spostata fisicamente nella tabella in una nuova posizione. Se devi separare la chiave primaria dalla chiave cluster (e talvolta lo fai), scegliere una buona chiave cluster è molto più difficile che scegliere una chiave primaria. Ci sono due fattori principali che guidano la progettazione di chiavi in ​​cluster:

  1. Il modello di accesso ai dati prevalente .
  2. Le considerazioni sull'archiviazione .

Modello di accesso ai dati . Con questo capisco il modo in cui la tabella viene interrogata e aggiornata. Ricorda che le chiavi raggruppate determinano l'ordine effettivo delle righe nella tabella. Per determinati modelli di accesso, alcuni layout fanno la differenza nel mondo per quanto riguarda la velocità delle query o per aggiornare la concorrenza:

  • dati attuali rispetto a quelli di archivio. In molte applicazioni si accede frequentemente ai dati relativi al mese in corso, mentre a quello passato si accede raramente. In questi casi, il design della tabella utilizza il partizionamento della tabella per data di transazione, spesso utilizzando un algoritmo a finestra scorrevole. La partizione del mese corrente viene conservata su un filegroup situato su un disco veloce a caldo, i vecchi dati archiviati vengono spostati in filegroup ospitati su uno spazio di archiviazione più economico ma più lento. Ovviamente in questo caso la chiave cluster (data) non è la chiave primaria (transaction id). La separazione dei due è determinata dai requisiti di scalabilità, poiché Query Optimizer sarà in grado di rilevare che le query sono interessate solo alla partizione corrente e non esamineranno nemmeno quelle storiche.

  • Elaborazione stile coda FIFO. In questo caso la tabella ha due punti caldi:la coda in cui si verificano gli inserti (in coda) e la testa in cui si verificano le eliminazioni (in coda). La chiave cluster deve tenerne conto e organizzare la tabella in modo da separare fisicamente la posizione di coda e testa sul disco, al fine di consentire la concorrenza tra enqueue e dequeue, ad es. utilizzando una chiave dell'ordine di accodamento. In puro code questa chiave cluster è l'unica chiave, poiché non esiste una chiave primaria sulla tabella (contiene messaggi , non entità ). Ma la maggior parte delle volte la coda non è pura, funge anche da memoria per le entità e la linea tra la coda e la tabella è sfocato. In questo caso esiste anche una chiave primaria, che non può essere la chiave cluster:le entità possono essere accodate nuovamente, modificando così il valore della chiave cluster dell'ordine di accodamento, ma non possono modificare il valore della chiave primaria. La mancata visualizzazione della separazione è il motivo principale per cui le code supportate da tabelle utente sono così notoriamente difficili da ottenere e piene di deadlock:perché l'accodamento e l'annullamento della coda si verificano interfogliati attraverso il tavolo, anziché localizzati in coda e all'inizio della coda.

  • Elaborazione correlata. Quando l'applicazione è ben progettata, partiziona l'elaborazione degli elementi correlati tra i suoi thread di lavoro. Ad esempio, un processore è progettato per avere 8 thread di lavoro (diciamo che corrispondano alle 8 CPU sul server) in modo che i processori suddividano i dati tra loro, ad es. il lavoratore 1 preleva solo i conti da A a E, il lavoratore 2 da F a J ecc. In questi casi la tabella dovrebbe essere effettivamente raggruppata dal nome del conto (o da una chiave composta che ha la prima lettera del nome del conto all'estrema sinistra), in modo che i lavoratori localizzino le loro query e gli aggiornamenti nella tabella. Una tabella del genere avrebbe 8 punti caldi distinti, attorno all'area in cui ogni lavoratore si concentra al momento, ma l'importante è che non si sovrappongano (nessun blocco). Questo tipo di progettazione è prevalente nei progetti OLTP ad alta velocità effettiva e nei carichi di benchmark TPCC, dove questo tipo di partizionamento si riflette anche nella posizione di memoria delle pagine caricate nel pool di buffer (località NUMA), ma sto divagando.

Considerazioni sull'archiviazione . La chiave cluster larghezza ha enormi ripercussioni nell'archiviazione della tabella. Per uno, la chiave occupa spazio in ogni pagina non foglia dell'albero b, quindi una chiave grande occuperà più spazio. In secondo luogo, e spesso più importante, è che la chiave cluster viene utilizzata come chiave di ricerca da ogni chiave non cluster, quindi ogni la chiave non in cluster dovrà memorizzare l'intera larghezza della chiave in cluster per ogni riga. Questo è ciò che rende le chiavi cluster di grandi dimensioni come varchar(256) e guid scelte sbagliate per le chiavi dell'indice cluster.
Inoltre, la scelta della chiave ha un impatto sulla frammentazione dell'indice cluster, a volte incidendo drasticamente sulle prestazioni.

Queste due forze a volte possono essere antagoniste, il modello di accesso ai dati richiede una certa chiave cluster di grandi dimensioni che causerà problemi di archiviazione. In questi casi è ovviamente necessario un equilibrio, ma non esiste una formula magica. Misuri e provi per arrivare al punto debole.

Allora cosa ricaviamo da tutto questo? Inizia sempre considerando la chiave cluster che è anche la chiave primaria del modulo entity_id IDENTITY(1,1) NOT NULL . Separare i due e organizzare la tabella di conseguenza (es. partizione per data) quando appropriato.