Quali sono le considerazioni sulle prestazioni tra l'utilizzo di un ampio PK vs una chiave sintetica separata e UQ?


10

Ho diverse tabelle in cui i record possono essere identificati in modo univoco con diversi settori di attività. In passato ho usato questi campi come PK, tenendo presenti questi vantaggi:

  • Semplicità; non ci sono campi estranei e solo un indice
  • Il clustering consente di unire rapidamente join e filtri basati sull'intervallo

Tuttavia, ho sentito un caso fatto per creare un IDENTITY INTPK sintetico e invece applicare la chiave aziendale con un UNIQUEvincolo separato . Il vantaggio è che lo stretto PK crea indici secondari molto più piccoli.

Se una tabella non ha indici diversi dal PK, non vedo alcun motivo per favorire il secondo approccio, sebbene in una tabella di grandi dimensioni è probabilmente meglio supporre che gli indici possano essere necessari in futuro, e quindi favorire lo stretto PK sintetico . Mi manca qualche considerazione?

Per inciso, non sto discutendo contro l'uso di chiavi sintetiche nei data warehouse, sono solo interessato a quando utilizzare un singolo PK ampio e quando utilizzare un PK stretto più un ampio Regno Unito.


1
potresti trovare questo o questo utile tra le altre domande sul sito
Jack dice di provare topanswers.xyz il

Risposte:


11

Non ci sono svantaggi significativi utilizzando la chiave naturale come indice cluster

  • non ci sono indici non cluster
  • nessuna chiave esterna che fa riferimento a questa tabella (è una riga principale)

Il rovescio della medaglia sarebbe l'aumento della divisione delle pagine in quanto gli inserimenti di dati sarebbero distribuiti in tutti i dati, anziché alla fine.

Laddove si disponga di indici FK o NC, l'utilizzo di un indice cluster ristretto, numerico e crescente presenta vantaggi. Ripeti solo pochi byte di dati per ogni voce NC o FK, non la chiave business / natural while.

Per quanto riguarda il motivo, leggi anche i 5 articoli di Google

Nota Ho evitato l'uso della "chiave primaria".

È possibile avere l'indice cluster sulla chiave surrogata ma mantenere il PK sulle regole aziendali ma come non cluster. Assicurati solo che il cluster sia unico perché SQL aggiungerà un "uniquifier" per renderlo tale.

Infine, può avere senso avere una chiave surrogata ma non alla cieca su ogni tabella : molte tabelle non ne hanno bisogno, o dove una chiave composta dalle tabelle principali sarà sufficiente


+1 per la sig.ra Tripp eccellente articoli in indicizzazione.
Fabricio Araujo,

2
+1 per il punto in cui le prestazioni non hanno nulla a che fare con le chiavi primarie e tutto con gli indici.
nvogel,

4

Anche se rischio di affermare ciò che è ovvio, un indice su una chiave surrogata (un numero ID) è utile se è necessario individuare le cose in base al loro numero ID. Gli utenti non hanno a che fare con il numero ID; si occuperanno di testo leggibile dall'uomo. Quindi devi passare molto intorno al testo e al suo numero ID, in modo che l'interfaccia utente possa visualizzare il testo e operare sul numero ID.

I dbms useranno quel tipo di indice per supportare le chiavi esterne, se le definisci in quel modo.

A volte puoi migliorare le prestazioni usando i numeri ID come chiavi esterne, ma non è un miglioramento assoluto. Sul nostro sistema OLTP, le chiavi esterne che utilizzano chiavi naturali hanno sovraperformato le chiavi esterne utilizzando i numeri ID su una suite di test di circa 130 query (credo) rappresentative. (Poiché le informazioni importanti vengono spesso trasportate nelle chiavi, l'uso delle chiavi naturali ha evitato molti join.) L'accelerazione mediana era un fattore di 85 (i join che utilizzavano numeri ID impiegavano 85 volte in più per restituire le righe).

I test hanno dimostrato che i join sui numeri ID non avrebbero prestazioni più veloci rispetto alle letture su chiavi naturali nel nostro database fino a quando alcune tabelle non raggiungessero milioni di righe. La larghezza della riga ha molto a che fare con questo: righe più larghe significano meno righe in una pagina, quindi devi leggere più pagine per ottenere 'n' righe. Quasi tutti i nostri tavoli sono in 5NF; la maggior parte dei tavoli sono abbastanza stretti.

Quando i join iniziano a essere eseguiti, eseguire qui semplici letture , l'inserimento di tabelle e indici critici su un disco a stato solido potrebbe livellare le prestazioni in centinaia di milioni di righe.


3

Ho un intero database oltp progettato utilizzando colonne di identità per clustering + pk. Funziona abbastanza velocemente su insert / seek ma ho riscontrato alcuni problemi:
1. l'opzione di riempimento dell'indice è inutile perché gli inserimenti avvengono solo alla fine dell'indice
2. più spazio di archiviazione. Ho tabelle con decine di milioni di record e 1 int occupa spazio da solo. Ogni tabella con una colonna di identità per il suo pk deve avere un altro indice per le ricerche di lavoro, quindi è necessario ancora più spazio di archiviazione.
3. scalabilità. Questo è il problema peggiore. Poiché ogni inserto arriva alla fine dell'indice, ogni inserto solleciterà solo la fine dell'indice (allocazione, io per le scritture, ecc.). Utilizzando una chiave business come chiave di clustering è possibile distribuire gli inserti in modo uniforme sull'indice. Ciò significa che hai appena eliminato un grande hotspot. È possibile utilizzare facilmente più file per un indice, ogni file su un'unità separata, ciascuna unità funziona separatamente.

Ho iniziato a cambiare le mie tabelle da colonne di identità a chiavi naturali (forse separate per clustering e pk). Adesso mi sento meglio.

Suggerirei quanto segue (almeno per un db oltp):
1. usa come chiave di clustering le colonne giuste nell'ordine giusto per ottimizzare le query più frequenti
2. usa un pk le colonne giuste che hanno senso per la tua tabella

Se la chiave cluster non è semplice e contiene caratteri (char [], varchar, nvarchar), penso che la risposta sia "dipende", è necessario analizzare singolarmente ogni caso.

Mantengo il seguente principio: ottimizzare per la query più comune minimizzando al contempo lo scenario peggiore.

Ho quasi dimenticato un esempio. Ho alcune tabelle che fanno riferimento a se stesse. Se quella tabella ha una colonna identità per la sua chiave primaria, l'inserimento di una riga potrebbe richiedere un aggiornamento e l'inserimento di più di una riga alla volta potrebbe essere difficile se non impossibile (dipende dalla struttura della tabella).


4
Il tuo concetto di "hotspot" è un mito: dba.stackexchange.com/questions/1584/… E quando dici "Adesso mi sento meglio." hai benchmark?
gbn

4
Sì, le scritture vengono eseguite in memoria non direttamente sul disco. Se si scrivono 20 nuove righe in una pagina, al momento del checkpoint si verifica solo 1 scrittura fisica nel file di dati.
mrdenny,

@mrdenny con abbastanza inserti che scrivono tutto alla fine dell'indice invierebbe tutte le richieste io write allo stesso file. Ho il sospetto che usando le normali transazioni oltp questo scenario sia difficile da riprodurre, ma usando alcuni scenari speciali come l'inserimento di massa / batch di record, l'uso di ssis per spostare alcuni dati aziendali vi porterà lì.
Catalin Adler,

1
@ user973156 Sì, tutte le richieste farebbero allo stesso file, ma le scritture in realtà non vanno sul disco fino al checkpoint che avviene solo ogni minuto (per impostazione predefinita) o quando il buffer di scrittura è pieno al 50%. Non importa come si scrivono i dati che questa regola si applica ancora.
mrdenny,

2
@ user973156 L'uso di una chiave di clustering distribuita casualmente provocherà la frammentazione dell'indice. La frammentazione dell'indice causerà problemi di prestazioni. E la tua tabella diventerà abbastanza grande da richiedere "molto tempo" per eseguire la deframmentazione dell'indice e consumare spazio di log e potenzialmente spazio tempDB. Quando ho persone come Kimberly Tripp che mi dicono che è una buona idea, ascolto. ( sqlskills.com/BLOGS/KIMBERLY/post/… )
Matt M

2

Dal punto di vista delle prestazioni, la scelta di quale chiave è la chiave "primaria" non fa alcuna differenza. Non vi è alcuna differenza tra l'utilizzo di un PRIMARY KEY e un vincolo UNIQUE per applicare le chiavi.

Le prestazioni sono determinate dalla selezione e dal tipo di indici e altre opzioni di archiviazione e dal modo in cui le chiavi vengono utilizzate nelle query e nel codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.