Una chiave esterna crea automaticamente un indice?


389

Mi è stato detto che se avessi chiave esterna due tabelle, che SQL Server creerà qualcosa di simile a un indice nella tabella figlio. Ho difficoltà a credere che questo sia vero, ma non riesco a trovare molto là fuori in relazione specificamente a questo.

La mia vera ragione per chiederlo è perché stiamo riscontrando tempi di risposta molto lenti in un'istruzione di eliminazione rispetto a una tabella che probabilmente ha 15 tabelle correlate. Ho chiesto al nostro addetto al database e mi dice che se c'è una chiave esterna nei campi, allora si comporta come un indice. Qual è la tua esperienza con questo? Devo aggiungere indici su tutti i campi chiave esterni o sono solo sovraccarichi non necessari?


Ho la stessa comprensione del tuo ragazzo DB - che gli FK in realtà creano un indice.
Vinnie,

9
No - un FK NON crea automaticamente un indice. Ha senso crearne uno, ma NON viene eseguito automaticamente da SQL Server.
marc_s

47
non è sciocco chiederlo a tutti!
marc_s

5
Se si ottengono eliminazioni lente e la tabella da cui si sta eliminando a cui fanno riferimento altre tabelle, probabilmente si otterrà un aumento delle prestazioni indicizzando le chiavi esterne nelle altre tabelle. Questo perché quando SQL elimina una riga, deve verificare l'integrità referenziale sulla riga. Per fare ciò, ovviamente, è necessario verificare che non esistano altre righe che fanno riferimento alla riga che si sta eliminando.
Noel Kennedy,

3
Direi che un tizio del database che non sapeva che questo doveva avere un serio bisogno di allenamento. Le persone del database sono responsabili delle prestazioni, è loro compito conoscere questo genere di cose. Ciò suggerisce una grave incompetenza.
HLGEM,

Risposte:


343

Una chiave esterna è un vincolo, una relazione tra due tabelle, che non ha nulla a che fare con un indice in sé.

Ma è risaputo che ha molto senso indicizzare tutte le colonne che fanno parte di qualsiasi relazione di chiave esterna, perché attraverso una relazione FK, è spesso necessario cercare una tabella correlata ed estrarre determinate righe in base a un singolo valore o un intervallo di valori.

Quindi ha senso indicizzare tutte le colonne coinvolte in un FK, ma un FK in sé non è un indice.

Leggi l'eccellente articolo di Kimberly Tripp "Quando SQL Server ha smesso di inserire indici nelle colonne di chiave esterna?" .


Sì. Sono quasi certo che PostgreSQL crei un indice. Sono abbastanza sicuro che lo faccia MySQL. Rendere l'indice ha molto senso, ma NON È NECESSARIO. Dopotutto, perché fare riferimento a qualcosa se ogni volta che il DB va a cercarlo deve fare un scancan?
MBCook

Questo articolo di cui sopra è un po 'confuso perché il server SQL o qualsiasi altro database non inserisce mai un indice in FK.
vsingh

7
@vsingh: questo è esattamente ciò che l'articolo cerca di comunicare - è un'idea sbagliata comune che un FK crei automaticamente un indice - non lo fa.
marc_s

5
@MBCook No, PostgreSQL non senza (almeno in 9.2 o qualsiasi versione precedente) crea automaticamente un indice sul lato riferimento di una relazione chiave esterna definita con REFERENCES. Crea automaticamente un UNIQUEindice per un PRIMARY KEYo UNIQUEvincolo e richiede che UNIQUEsia presente un indice per la fine referenziata di una relazione di chiave esterna, ma non fa nulla automaticamente per la fine di referenziazione , sebbene spesso sia una buona idea crearne uno da soli. Vedi stackoverflow.com/questions/970562/…
Craig Ringer il

16
La confusione può esistere perché MySQL InnoDB richiede entrambi e crea automaticamente un indice quando si aggiunge una chiave esterna - dev.mysql.com/doc/refman/5.5/en/…
humbads

42

Caspita, le risposte sono su tutta la mappa. Quindi la documentazione dice:

Un vincolo FOREIGN KEY è un candidato per un indice perché:

  • Le modifiche ai vincoli PRIMARY KEY vengono verificate con i vincoli FOREIGN KEY nelle tabelle correlate.

  • Le colonne chiave esterna vengono spesso utilizzate nei criteri di join quando i dati delle tabelle correlate vengono combinati nelle query facendo corrispondere le colonne nel vincolo FOREIGN KEY di una tabella con le colonne chiave primaria o unica nell'altra tabella. Un indice consente a Microsoft® SQL Server ™ 2000 di trovare rapidamente i dati correlati nella tabella delle chiavi esterne. Tuttavia, la creazione di questo indice non è un requisito. I dati di due tabelle correlate possono essere combinati anche se non sono definiti vincoli PRIMARY KEY o FOREIGN KEY tra le tabelle, ma una relazione di chiave esterna tra due tabelle indica che le due tabelle sono state ottimizzate per essere combinate in una query che utilizza le chiavi come i suoi criteri.

Quindi sembra abbastanza chiaro (anche se la documentazione è un po 'confusa) che in realtà non crea un indice.


5
Esatto - è un CANDIDATO per un indice - ma non viene creato automaticamente come tale! Abbastanza chiaro in realtà, IMHO :-)
marc_s

4
Ho trovato confusa questa parte: "una relazione di chiave esterna tra due tabelle indica che le due tabelle sono state ottimizzate per essere combinate in una query che utilizza le chiavi come criterio". Che dovrebbe leggere "... due tabelle dovrebbero essere ottimizzate ..."
Yishai,

18

No, non esiste un indice implicito nei campi chiave esterna, altrimenti perché Microsoft dovrebbe dire "Creare un indice su una chiave esterna è spesso utile" . Il vostro collega può essere fonte di confusione il campo chiave esterna nella tabella del rinvio la chiave primaria nelle cui da tavolo - le chiavi primarie non creare un indice implicito.


che cos'è "un indice implicito"? implica semplicemente che c'è un * albero senza crearlo?
Stephanie Pagina

1
@Stephanie Page: È un'espressione che ho appena inventato per questa risposta per indicare un indice che viene creato automaticamente. Se si dichiara una chiave primaria, SQL Server crea e indicizza automaticamente per essa. Ma non per dichiarare una chiave esterna (alcuni altri sistemi DB lo fanno).
Michael Borgwardt,

7

SQL Server crea automaticamente gli indici per le chiavi primarie, ma non per le chiavi esterne. Creare l'indice per le chiavi esterne. Probabilmente vale la pena.


6

Supponi di avere un grande tavolo chiamato ordini e un piccolo tavolo chiamato clienti. C'è una chiave esterna da un ordine a un cliente. Ora se si elimina un cliente, SQL Server deve verificare che non vi siano ordini orfani; se ci sono, genera un errore.

Per verificare se ci sono ordini, Sql Server deve cercare nella tabella dei grandi ordini. Ora se c'è un indice, la ricerca sarà veloce; in caso contrario, la ricerca sarà lenta.

Quindi, in questo caso, l'eliminazione lenta potrebbe essere spiegata dall'assenza di un indice. Soprattutto se Sql Server dovrebbe cercare 15 grandi tabelle senza un indice.

PS Se la chiave esterna ha ON DELETE CASCADE, Sql Server deve ancora cercare la tabella degli ordini, ma quindi rimuovere tutti gli ordini che fanno riferimento al cliente eliminato.


Esatto - questo è il motivo per cui un indice su un FK ha molto senso (il più delle volte)
marc_s

1
La maggior parte delle volte? Sembra che questo sia il caso di una cancellazione da un genitore. Se la maggior parte delle volte si elimina dai genitori, immagino sia vero.
Stephanie Pagina

6

Le chiavi esterne non creano indici. Solo i vincoli chiave alternativa (UNIQUE) e i vincoli chiave primaria creano indici. Questo è vero in Oracle e SQL Server.


3

Non per mia conoscenza. Una chiave esterna aggiunge solo un vincolo al fatto che il valore nella chiave figlio sia rappresentato anche da qualche parte nella colonna padre. Non sta dicendo al database che anche la chiave figlio deve essere indicizzata, solo vincolata.


3

A rigor di termini, le chiavi esterne non hanno assolutamente nulla a che fare con gli indici, sì. Ma, come hanno sottolineato gli altoparlanti sopra di me, ha senso crearne uno per accelerare le ricerche FK. Infatti, in MySQL, se non specifichi un indice nella tua dichiarazione FK, il motore (InnoDB) lo crea automaticamente per te.


3

In PostgeSql puoi controllare tu stesso gli indici se premi \ d tablename

Vedrai che gli indici btree sono stati creati automaticamente su colonne con chiave primaria e vincoli univoci, ma non su colonne con chiavi esterne.

Penso che risponda alla tua domanda almeno per Postgres.


Spiacenti, non ho notato che la domanda riguarda MS SQL Server ma dopo aver pubblicato la risposta. Probabilmente potrebbe ancora aiutare qualcuno ...
Gregor

2

Ho notato che Entity Framework 6.1 puntato su MSSQL aggiunge automaticamente indici su chiavi esterne.


Non credo che lo faccia se si contrassegna manualmente la colonna come parte di un indice (ad esempio se si sta creando un indice composito su più membri)
Rowland Shaw

0

InnoDB richiede indici su chiavi esterne e chiavi di riferimento in modo che i controlli delle chiavi esterne possano essere veloci e non richiedere una scansione della tabella. Nella tabella di riferimento, deve esserci un indice in cui le colonne della chiave esterna sono elencate come prime colonne nello stesso ordine.

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.