chiave primaria sql e index


106

Supponiamo di avere una riga ID (int) in un database impostato come chiave primaria. Se interrogo spesso l'ID, devo anche indicizzarlo? Oppure essendo una chiave primaria significa che è già indicizzata?

Il motivo per cui lo chiedo è perché in MS SQL Server posso creare un indice su questo ID, che come ho affermato è la mia chiave primaria.

Modifica: una domanda aggiuntiva: indicizzare ulteriormente la chiave primaria?

Risposte:


73

Hai ragione, è fonte di confusione che SQL Server ti consenta di creare indici duplicati sugli stessi campi. Ma il fatto che tu possa crearne un altro non indica che anche l'indice PK non esiste già.

L'indice aggiuntivo non funziona, ma l'unico danno (molto piccolo) è la dimensione del file aggiuntivo e il sovraccarico per la creazione di righe.


39
I danni degli indici inutilizzati sono davvero molto dannosi. Per prima cosa, gli indici consumano lo spazio di archiviazione. Per un'altra cosa, rallenta le scritture e gli aggiornamenti. Elimina sempre gli indici che non verranno utilizzati.
Pacerier

50

Come tutti gli altri hanno già detto, le chiavi primarie vengono indicizzate automaticamente.

La creazione di più indici nella colonna della chiave primaria ha senso solo quando è necessario ottimizzare una query che utilizza la chiave primaria e alcune altre colonne specifiche. Creando un altro indice sulla colonna della chiave primaria e includendovi alcune altre colonne, è possibile raggiungere l'ottimizzazione desiderata per una query.

Ad esempio, hai una tabella con molte colonne ma stai solo interrogando le colonne ID, Nome e Indirizzo. Prendendo ID come chiave primaria, possiamo creare il seguente indice basato su ID ma che include le colonne Nome e Indirizzo.

CREATE NONCLUSTERED INDEX MyIndex
ON MyTable(ID)
INCLUDE (Name, Address)

Quindi, quando usi questa query:

SELECT ID, Name, Address FROM MyTable WHERE ID > 1000

SQL Server ti darà il risultato usando solo l'indice che hai creato e non leggerà nulla dalla tabella effettiva.


28

NOTA: questa risposta riguarda lo sviluppo di classe enterprise in generale .

Si tratta di un problema di RDBMS, non solo di SQL Server, e il comportamento può essere molto interessante. Per uno, mentre è comune che le chiavi primarie siano indicizzate automaticamente (in modo univoco), NON è assoluto. Ci sono momenti in cui è essenziale che una chiave primaria NON sia indicizzata in modo univoco.

Nella maggior parte degli RDBMS, verrà creato automaticamente un indice univoco su una chiave primaria se non ne esiste già una . Pertanto, è possibile creare il proprio indice sulla colonna della chiave primaria prima di dichiararlo come chiave primaria, quindi tale indice verrà utilizzato (se accettabile) dal motore di database quando si applica la dichiarazione della chiave primaria. Spesso è possibile creare la chiave primaria e consentire la creazione del suo indice univoco predefinito, quindi creare il proprio indice alternativo su quella colonna, quindi rilasciare l'indice predefinito.

Ora per la parte divertente: quando NON vuoi un indice di chiave primaria univoco? Non ne vuoi uno e non puoi tollerarne uno, quando la tua tabella acquisisce dati (righe) sufficienti per rendere troppo costosa la manutenzione dell'indice. Questo varia in base all'hardware, al motore RDBMS, alle caratteristiche della tabella e del database e al carico di sistema. Tuttavia, in genere inizia a manifestarsi quando una tabella raggiunge alcuni milioni di righe.

Il problema essenziale è che ogni inserimento di una riga o aggiornamento della colonna della chiave primaria si traduce in una scansione dell'indice per garantire l'unicità. Quella scansione dell'indice univoca (o il suo equivalente in qualsiasi RDBMS) diventa molto più costosa man mano che la tabella cresce, finché non domina le prestazioni della tabella.

Ho affrontato questo problema molte volte con tabelle grandi fino a due miliardi di righe, 8 TB di spazio di archiviazione e quaranta milioni di inserimenti di righe al giorno. Mi è stato assegnato il compito di riprogettare il sistema coinvolto, che includeva l'eliminazione dell'indice della chiave primaria univoca praticamente come passaggio uno. In effetti, l'abbassamento di quell'indice era necessario in produzione semplicemente per riprendersi da un'interruzione, prima ancora di avvicinarsi a una riprogettazione. La riprogettazione includeva la ricerca di altri modi per garantire l'unicità della chiave primaria e per fornire un rapido accesso ai dati.


Cosa succede se la chiave è una chiave autoincrement int o bigint? SQL Server è abbastanza intelligente da non eseguire una scansione dell'indice univoca in questo caso?
Quillbreaker

1
@quillbreaker: IDENTITYnon è garantito che un campo sia unico. Dopo tutto, gli utenti possono inserire valori duplicati se utilizzano IDENTITY_INSERT.

So che questo è un argomento antico, ma non capisco come una scansione di unicità di un indice possa essere un tale carico sul sistema. Una scansione dell'albero B + dovrebbe essere O (log n) * v dove v è vincolato all'overhead per la frammentazione dell'indice, l'equilibrio imperfetto dell'albero, ecc. Quindi 2 miliardi di righe sarebbero in base logaritmica 2 di 2.000.000.000 (circa 31 seek) volte, diciamo, 2 o 3 o anche 10. 40 milioni di inserti al giorno sono circa 462 / sec, ~ 100 IO per inserto ... Ahh ... Oh. Vedo. E questo era prima degli SSD diffusi.
Charles Burns

A meno che non abbiate eliminato il vincolo di unicità, il sovraccarico di controllare l'unicità di ciascuna delle righe non sarebbe molto maggiore?
Max Candocia

20

Le chiavi primarie sono sempre indicizzate per impostazione predefinita.

È possibile definire una chiave primaria in SQL Server 2012 utilizzando SQL Server Management Studio o Transact-SQL. La creazione di una chiave primaria crea automaticamente un indice univoco, cluster o non cluster corrispondente.

http://technet.microsoft.com/en-us/library/ms189039.aspx


9

Ecco il passaggio dall'MSDN :

Quando si specifica un vincolo PRIMARY KEY per una tabella, il Motore di database applica l'univocità dei dati creando un indice univoco per le colonne della chiave primaria. Questo indice consente anche un accesso rapido ai dati quando la chiave primaria viene utilizzata nelle query. Pertanto, le chiavi primarie scelte devono seguire le regole per la creazione di indici univoci.


8

una PK diventerà un indice cluster a meno che non si specifichi non cluster


3

La dichiarazione di un vincolo PRIMARY KEYor UNIQUEfa sì che SQL Server crei automaticamente un indice.

È possibile creare un indice univoco senza corrispondere a un vincolo, ma un vincolo (chiave primaria o univoco) non può esistere senza avere un indice univoco.

Da qui, la creazione di un vincolo:

  • causare la creazione di un indice con lo stesso nome
  • negare l'eliminazione dell'indice creato poiché il vincolo non può esistere senza di esso

e allo stesso tempo abbandonare il vincolo farà cadere l'indice associato.

Quindi, esiste una differenza effettiva tra a PRIMARY KEYo UNIQUE INDEX:

  • NULLi valori non sono consentiti in PRIMARY KEY, ma consentiti in UNIQUEindex; e come negli operatori set (UNION, EXCEPT, INTERSECT), qui NULL = NULLsignifica che puoi avere un solo valore dato che due NULLs sono duplicati l'uno dell'altro;
  • ne PRIMARY KEYpuò esistere solo uno per tabella mentre possono essere creati 999 indici univoci
  • quando PRIMARY KEYviene creato il vincolo, viene creato come cluster a meno che non sia già presente un indice cluster sulla tabella o NONCLUSTEREDvenga utilizzato nella sua definizione; quando l' UNIQUEindice viene creato, viene creato come a NONCLUSTEREDmeno che non sia specifico di essere CLUSTEREDe tale già non esiste;

2

Rendendola una chiave primaria dovrebbe anche creare automaticamente un indice per essa.


1

In SQL Server, in genere, la chiave primaria viene indicizzata automaticamente. Questo è vero, ma non garantisce una query più veloce. La chiave primaria ti darà prestazioni eccellenti quando c'è solo 1 campo come chiave primaria. Tuttavia, quando sono presenti più campi come chiave primaria, l'indice si basa su tali campi.

Ad esempio: i campi A, B, C sono la chiave primaria, quindi quando esegui una query basata su quei 3 campi nella tua CLAUSOLA DOVE, le prestazioni sono buone, MA quando vuoi eseguire una query con solo il campo C nella CLAUSOLA DOVE, devi non otterrà buone prestazioni. Pertanto, per ottenere le prestazioni operative, sarà necessario indicizzare manualmente il campo C.

Il più delle volte, non vedrai il problema finché non raggiungerai più di 1 milione di record.


0

Ho un enorme database senza indice (separato).

Ogni volta che eseguo una query tramite la chiave primaria, i risultati sono, a tutti gli effetti, immediati.


Questo perché il PK è un indice cluster, guarda il tuo piano di query
SQLMenace,

0

le chiavi primarie vengono indicizzate automaticamente

puoi creare indici aggiuntivi usando il pk a seconda del tuo utilizzo

  • index zip_code, id può essere utile se selezioni spesso per zip_code e id
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.