2009-02-03 10 views
118

Supponiamo di avere 2 tabelle, prodotti e categorie di prodotti. Entrambe le tabelle hanno una relazione su CategoryId. E questa è la domanda.La chiave esterna migliora le prestazioni della query?

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 il piano di esecuzione, tabella ProductCategories esegue ricerca indice cluster, che è come aspettativa. Ma per i prodotti da tavola, 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 l'indice su Products.CategoryId. Quando creo di nuovo il piano di esecuzione, entrambe le tabelle eseguono la ricerca dell'indice. E il costo del sottostrato stimato viene ridotto molto.

Le mie domande sono:

  1. Accanto FK aiuta il vincolo rapporto, Ha qualche altra utilità? Migliora le prestazioni della query?

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

risposta

155

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 devi creare indici su tutti i campi FK per migliorare i tempi di ricerca.

+9

+1: il modello è una cosa. La performance è un'altra. –

+27

I buoni modelli (generalmente) hanno prestazioni migliori. –

+7

"Le chiavi esterne sono uno strumento di integrità relazionale": si prega di utilizzare la parola "relazionale" con attenzione. Le chiavi esterne sono un concetto di database, una mano breve per un vincolo di integrità referenziale. Non fanno parte del modello relazionale. Immagino tu abbia fatto un refuso. – onedaywhen

13

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

Eventuali implicazioni/miglioramenti delle prestazioni saranno specifici della tecnologia del database utilizzata e sono secondari rispetto 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 chiarisca le cose per te ma non esitate a richiedere maggiori dettagli.

+4

Le prestazioni sono più facili da vendere rispetto all'integrità del database. –

+8

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

+0

@HLGEM Ottenere un errore [404] (http://en.wikipedia.org/wiki/HTTP_404) una volta ogni tanto è ancora abbastanza sopportabile. Avere un rendimento eccezionale in cambio di risorse più economiche e sistemi meno complessi, ora anche molto facilmente. Potresti essere interessato al [C.A.P. Teorema] (http://en.wikipedia.org/wiki/CAP_theorem). –

47

chiavi esterne può migliorare (e male) le prestazioni

  1. Come indicato qui: Foreign keys boost performance

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

Modifica

Come il link ora sembra essere morto (complimenti a Chris per averlo notato), che segue mostra l'essenza del perché le chiavi esterne possono migliorare (e ferito) le prestazioni.

Can Foreign key improve performance

Esteri vincolo di chiave a migliorare le prestazioni al momento della lettura dei dati ma allo stesso tempo rallenta le prestazioni al momento della Inserimento/modifica/cancellazione di dati.

In caso di lettura della query, l'ottimizzatore può utilizzare i vincoli di chiave esterna a creare piani di query più efficienti come i vincoli di chiave esterna sono regole pre-dichiarate. Ciò in genere comporta il passaggio da una parte del piano di query a perché ad esempio l'ottimizzatore può vedere che a causa di un vincolo di chiave esterna, non è necessario eseguire quella parte specifica del piano.

+2

Ecco un collegamento in cui vengono descritti i modi in cui possono ridurre le prestazioni http://www.devx.com/getHelpOn/10MinuteSolution/16595/0/page/2 – cmsjr

+2

Questo ha senso, ma ci si imbatte solo in questo elimina la dichiarazione. Forse la conclusione dovrebbe essere che in ambienti OLAP, gli FK non indicizzati migliorerebbero le prestazioni mentre negli ambienti OLTP, peggiorerebbero le prestazioni. –

+1

Il collegamento in questa risposta è morto. Questo è sfortunato in quanto è l'unico argomento qui per le FK che migliorano le prestazioni. –

3

È possibile utilizzarlo per rendere più efficiente una query. Ti consente di ristrutturare le query in SQL Server per utilizzare un join esterno anziché uno interno che rimuove la necessità di SQL Server di dover verificare se c'è un valore null nella colonna. Non è necessario inserire quel qualificatore perché la relazione con la chiave esterna lo rende già applicabile.

Quindi 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; 

Questo non sarà necessariamente fare una grande prestazione in piccole query, ma quando le tabelle diventano grandi può essere più efficiente.

+3

Non solo i join esterni sono tipicamente _less_ efficienti di inner join (http://stackoverflow.com/a/2726683/155892), ora le tue query sono fuorvianti: stai facendo affidamento sul database per trasformare implicitamente i tuoi join esterni in inner join (ripristinando la performance) invece di farlo esplicitamente –

4

La tua scommessa migliore è quella di utilizzare gli indici nei campi che utilizzi frequentemente. Se si utilizza SQL Server, è possibile utilizzare profiler per creare un profilo per un database specifico e prendere il file che emette e utilizzare la procedura guidata di ottimizzazione per ricevere consigli su dove posizionare gli indici. Mi piace anche usare il profiler per scovare le stored procedure a lungo termine, ho una lista dei peggiori 10 tra i peggiori che pubblico ogni settimana, mantiene le persone oneste: D.

1

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

1

L'aggiunta di una chiave esterna nella tabella non migliorerà le prestazioni, semplicemente dicendo che se si inserisce un record in una tabella di categorie ProductCategories si tenterà di trovare la colonna della chiave esterna con un valore presente nel valore della chiave primaria della tabella prodotti, questa ricerca, l'operazione è overhead sul tuo database ogni volta che aggiungi 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à utilizzando la chiave esterna invece di eseguire molte query per verificare che il record sia presente nel database del tuo programma.