Chiave esterna migliora le prestazioni delle query?


149

Supponiamo di avere 2 tabelle, prodotti e categorie di prodotti. Entrambe le tabelle hanno una relazione su CategoryId. E questa è la domanda.

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category
FROM Products p
INNER JOIN ProductCategories c ON p.CategoryId = c.CategoryId
WHERE c.CategoryId = 1;

Quando creo un piano di esecuzione, la tabella ProductCategories esegue la ricerca dell'indice del cluster, che è come aspettativa. Ma per i prodotti da tavolo, esegue la scansione dell'indice del cluster, il che mi fa dubitare. Perché FK non aiuta a migliorare le prestazioni delle query?

Quindi devo creare un indice su Products.CategoryId. Quando creo nuovamente il piano di esecuzione, entrambe le tabelle eseguono la ricerca dell'indice. E il costo stimato della sottostruttura è molto ridotto.

Le mie domande sono:

  1. Oltre a FK aiuta a limitare le relazioni, ha qualche altra utilità? Migliora le prestazioni delle query?

  2. Devo creare un indice su tutte le colonne FK (mi piace Products.CategoryId) in tutte le tabelle?

Risposte:


186

Le chiavi esterne sono uno strumento di integrità referenziale, non uno strumento di prestazioni. Almeno in SQL Server, la creazione di un FK non crea un indice associato e si dovrebbero creare indici su tutti i campi FK per migliorare i tempi di ricerca.


40
I buoni modelli (generalmente) hanno prestazioni migliori.
Kenny Evitt,

10
"Le chiavi esterne sono uno strumento di integrità relazionale": utilizzare con attenzione la parola "relazionale". Le chiavi esterne sono un concetto di database, una scorciatoia per un vincolo di integrità referenziale. Non fanno parte del modello relazionale. Presumo tu abbia fatto un refuso.
Onedayquando il

7
@Kenny Spesso sì, ma a volte un modello migliore costa di più. Caso in questione: le chiavi esterne causano più elaborazioni, non meno.
Hans,

8
chiavi esterne fanno migliorare le prestazioni, almeno in MySQL. Inoltre, hai ragione, la creazione di un FK non crea un indice; la creazione di un FK richiede un indice
Félix Gagnon-Grenier,

15
Questa risposta è praticamente inutile perché non risponde alla domanda. È bello sapere che le chiavi esterne non intendono avere un effetto (positivo) sulle prestazioni, ma la domanda riguardava la realtà, non le intenzioni.
Giovanni

58

Le chiavi esterne possono migliorare (e danneggiare) le prestazioni

  1. Come indicato qui: le chiavi esterne aumentano le prestazioni

  2. Dovresti sempre creare indici su colonne FK per ridurre le ricerche. SQL Server non lo fa automaticamente.

modificare

Dato che il collegamento ora sembra essere morto (complimenti a Chris per averlo notato) , il seguito mostra l'essenza del perché le chiavi esterne possono migliorare (e danneggiare) le prestazioni.

La chiave esterna può migliorare le prestazioni

Il vincolo di chiave esterna migliora le prestazioni al momento della lettura dei dati ma allo stesso tempo rallenta le prestazioni al momento dell'inserimento / modifica / eliminazione dei dati.

In caso di lettura della query, l'ottimizzatore può utilizzare i vincoli di chiave esterna per creare piani di query più efficienti poiché i vincoli di chiave esterna sono regole pre dichiarate. Questo di solito comporta il salto di una parte del piano di query perché, ad esempio, l'ottimizzatore può vedere che a causa di un vincolo di chiave esterna, non è necessario eseguire quella particolare parte del piano.


3
Ecco un link che descrive i modi in cui possono degradare le prestazioni devx.com/getHelpOn/10MinuteSolution/16595/0/page/2
cmsjr,

3
Questo ha senso, ma ti imbatterai in questo solo con un'enorme dichiarazione di eliminazione. Forse la conclusione dovrebbe essere che negli ambienti OLAP, gli FK non indicizzati migliorerebbero le prestazioni mentre negli ambienti OLTP, ne degraderebbero le prestazioni.
Lieven Keersmaekers,

1
Il link in questa risposta è morto. Questo è un peccato perché è l'unico argomento qui per gli FK che migliorano le prestazioni.
Chris Moschini,

1
@ChrisMoschini - Non ho notato il tuo commento fino ad ora. Come hai già detto, il link è morto ma l'essenza di esso è menzionata nel nuovo link (con i dettagli) che ho pubblicato.
Lieven Keersmaekers,

2
Collegamento Wayback Machine per Win! L'articolo è disponibile anche su SQLMag.com, qui .
John Eisbrener,

15

Una chiave esterna è un concetto DBMS per garantire l'integrità del database.

Eventuali implicazioni / miglioramenti delle prestazioni saranno specifici della tecnologia di database utilizzata e sono secondari allo scopo di una chiave esterna.

È buona norma in SQL Server assicurarsi che tutte le chiavi esterne abbiano almeno un indice non cluster su di esse.

Spero che questo ti chiarisca le cose, ma non esitare a richiedere maggiori dettagli.


9
@Kenny Evitt se non hai integrità, i tuoi dati sono inutili. Trovo che vende molto facilmente.
HLGEM,

@HLGEM Ottenere un errore 404 di tanto in tanto è ancora abbastanza sopportabile. Avere un rendimento eccezionale in cambio usando risorse più economiche e sistemi meno complessi, ora che vende anche molto facilmente. Potresti essere interessato al teorema della PAC .
Daniel Dinnyes,

8
@Daniel Dinnyes, l'integrità dei dati non consiste nell'ottenere un errore 404. Si tratta di avere dati utilizzabili. Si tratta di non perdere ordini e dati finanziari per i report, ad esempio a causa dell'incompetenza degli sviluppatori. Non esiste alcuna scusa per non utilizzare chiavi esterne.
HLGEM,

2
Sono d'accordo con HLGEM. Consentire al codice di gestire l'integrità non è sempre una buona idea. I dati vengono spesso utilizzati per prendere decisioni, ma se i dati sono danneggiati, la decisione non sarà accurata.
lepe

1
"Le chiavi esterne sono uno strumento di integrità relazionale": utilizzare con attenzione la parola "relazionale". Le chiavi esterne sono un concetto di database, una scorciatoia per un vincolo di integrità referenziale. Non fanno parte del modello relazionale. Presumo tu abbia fatto un refuso.
onedayquando il

4

La tua migliore scommessa sul rendimento è usare gli indici sui campi che usi di frequente. Se si utilizza SQL Server, è possibile utilizzare il profiler per creare un profilo per un database specifico e prendere il file che genera e utilizzare la procedura guidata di ottimizzazione per ricevere consigli su dove posizionare gli indici. Mi piace anche usare il profiler per svuotare le stored procedure di lunga durata, ho una delle dieci peggiori liste di autori di reati che pubblico ogni settimana, rende le persone oneste: D.


3

Puoi usarlo per rendere più efficiente una query. Consente di ristrutturare le query in SQL Server per utilizzare un join esterno anziché uno interno che rimuove i server sql necessari per controllare se è presente un null nella colonna. Non è necessario inserire quel qualificatore perché la relazione di chiave esterna già lo rinforza per te.

Così questo:

    select p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
from Products p inner join ProductCategories c on p.CategoryId = c.CategoryIdwhere c.CategoryId = 1;

Diventa questo:

SELECT p.ProductId, p.Name, c.CategoryId, c.Name AS Category 
FROM ProductCategories c 
LEFT OUTER JOIN Products P ON
c.CategoryId = p.CategoryId 
WHERE c.CategoryId = 1;

Ciò non produrrà necessariamente prestazioni eccezionali in piccole query, ma quando le tabelle diventano grandi può essere più efficiente.


3
I join esterni non sono solo in genere meno efficienti dei join interni ( stackoverflow.com/a/2726683/155892 ), ora le tue query sono fuorvianti: ti affidi al database per trasformare implicitamente i tuoi join esterni in join interni (ripristinando le prestazioni) invece di farlo esplicitamente
Mark Sowul

2

Per MySQL 5.7, può sicuramente velocizzare incredibilmente bene le query che coinvolgono più join!

Ho usato "Spiegazione" per comprendere la mia query e ho scoperto che stavo unendo 4-5 tabelle, dove non sono state utilizzate chiavi. Non ho fatto altro che aggiungere una chiave esterna a queste tabelle e il risultato è stato una riduzione del 90% del tempo di caricamento. Le query che hanno richiesto> 5 secondi ora richiedono 500 ms o meno.

Questo è un miglioramento ENORME!

E, come altri hanno già detto, ottieni l'ulteriore vantaggio di garantire l'integrità relazionale.

Oltre a ciò, garantire l'integrità referenziale ha anche i suoi vantaggi in termini di prestazioni. Ha l'effetto del secondo ordine di garantire che le tabelle che hanno la chiave esterna siano "aggiornate" con la tabella esterna. Supponi di avere una tabella degli utenti e una tabella dei commenti e che stai facendo alcune statistiche sulla tabella dei commenti. Probabilmente se cancelli duramente l'utente, non vuoi più nemmeno i loro commenti.


Le tabelle avevano gli indici richiesti per generare le chiavi esterne prima di aggiungerle?
George

1

L'aggiunta di una chiave esterna nella tabella non migliorerà le prestazioni, semplicemente dicendo che se stai inserendo un record in un database della tabella ProductCategories proverai a trovare la colonna chiave esterna ha un valore esistente nel valore della chiave primaria della tabella di prodotti, questa ricerca, l'operazione è sovraccarica nel database ogni volta che si aggiunge una nuova voce nella tabella ProductCategories. Quindi, aggiungendo una chiave esterna non migliorerà le prestazioni del database ma si prenderà cura dell'integrità del database. Sì, migliorerà le prestazioni del tuo db se stai controllando l'integrità usando una chiave esterna invece di eseguire molte query per verificare che il record sia presente nel database nel tuo programma.


0

Non so molto sul server SQL, ma nel caso di Oracle, avere una colonna di chiave esterna riduce le prestazioni del caricamento dei dati. Questo perché il database deve verificare l'integrità dei dati per ciascun inserto. E sì, come già accennato, avere un indice sulla colonna chiave esterna è una buona pratica.


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.