Domanda

Di recente ho migrato l'intero DB da myisam a innodb. Sono abbastanza nuovo in tutto ciò, quindi ho una domanda sull'uso della chiave esterna.

Diciamo che ho due tabelle: utenti, messaggi.

utenti

id (pr_key)
nome

Messaggi

id (pr_key)
user_id
Messaggio

I campi ID sono entrambi auto incrementati.

Quindi ora nelle mie domande mi unisco a queste 2 tabelle. È ancora necessario inserire una chiave esterna qui, in realtà non vedo un punto. Ha vantaggi in termini di prestazioni.

Se scelgo di inserire una chiave esterna qui, suppongo di dover rendere la pr_key dei messaggi sia id, sia user_id.

  

L'aggiunta dell'altro prim_key non solo richiederà più spazio e si tradurrà in prestazioni più lente.

     

Ora se la tabella ha due pr_keys e io eseguo solo una query su uno di essi, avrò comunque gli stessi vantaggi in termini di prestazioni. O devo usare esplicitamente le due chiavi.

So che in questo esempio cercherò su user_id, quindi è forse intelligente indicizzarlo comunque. Ma cosa succede se il campo è un campo in cui non ci sono ricerche. È comunque utile posizionare una chiave primaria multipla in questo campo, solo per la relazione hey esterna.

Grazie!

È stato utile?

Soluzione

Ha integrità dei dati .

impedirà al codice dell'applicazione di immettere user_id di 1234 nella tabella dei messaggi quando non ci sono utenti con id = 1234 nella tabella degli utenti. E impedirà all'applicazione di eliminare l'utente quando l'utente ha dei messaggi nella tabella dei messaggi.

Il nome del PK non deve corrispondere al nome dell'FK nella tabella figlio di riferimento.

" Se scelgo di inserire una chiave esterna qui presumo che devo rendere la chiave_pr_ di messaggi sia id, sia user_id. & Quot;

NO . Non si modifica la chiave nella tabella dei messaggi, si stabilisce semplicemente un vincolo di chiave esterna (FK) sulla colonna User_Id nella tabella dei messaggi, che fa riferimento (punta a) alla colonna id sulla tabella degli utenti. Non è richiesto alcun PK aggiuntivo nei messaggi e poiché PK è già univoco (non è possibile avere due messaggi con lo stesso messageId), rendendo il PK su id e user_id non è possibile aggiungere ulteriore unicità.)

La linea di fondo qui è che potresti avere un malinteso fondamentale su cosa siano realmente una chiave primaria e una chiave esterna.

  • Un PK è un vincolo all'unicità di una riga, richiede un indice.
  • Un FK è un vincolo sul valore di una colonna (impone che il valore esista come valore PK in qualche altra tabella di riferimento) non richiede un indice.

@Noah, dai un'occhiata a questa Altra domanda SO

Altri suggerimenti

Sia che si stabilisca o meno una regola formale FOREIGN KEY sui messaggi (user_id), il semplice fatto è che si tratta di una relazione di chiave esterna.

Innanzitutto, ricorda che una chiave primaria corretta su una tabella dovrebbe essere sufficiente per identificare in modo univoco ogni record nella tabella. Considerando che ogni messaggio lo avrà già con il campo id , non è necessario né si desidera avvolgere user_id nella chiave primaria della tabella dei messaggi.

In secondo luogo, come già affermato da Charles dichiarando una CHIAVE ESTERA sui messaggi (user_id) che gli utenti REFERENCES (id) ti consentiranno di garantire l'integrità dei tuoi dati. Utilizzando un vincolo di chiave esterna è possibile specificare cosa fare quando viene eliminato un record nella tabella degli utenti con record corrispondenti nella tabella dei messaggi. Le tue scelte sono ON DELETE CASCADE (elimina tutti i record figlio per questo record utente), ON DELETE RESTRICT (non consentire a un utente di essere eliminato con record nella tabella dei messaggi), ON DELETE NO AZIONE (ignora le operazioni di eliminazione) , ON DELETE SET NULL (conserva i record figlio ma imposta il campo user_id su NULL).

Ognuna di queste opzioni è appropriata a seconda delle circostanze, ma la cosa più importante qui è che è possibile prevenire puntatori null imprevisti dalla tabella figlio alla tabella padre.

In terzo luogo, stabilire la relazione FOREIGN KEY fornirà miglioramenti delle prestazioni in quanto genererà un INDICE sui messaggi (user_id) che corrisponde al PRIMARY KEY nella tabella degli utenti. Quando esegui una query che si unisce a questi campi, vedrai che il numero di record che devono essere interrogati per restituire i record figlio è sostanzialmente ridotto rispetto al fatto che non sia stato stabilito il CHIAVE ESTERO.

@Charles Bretana: la domanda a cui ci si collega è specifica di Microsoft SQL Server. La domanda qui riguarda MySQL / InnoDB.

Consiglierei di consultare la documentazione per Vincoli di chiave esterna InnoDB .

  

InnoDB richiede indici su estero   chiavi e chiavi di riferimento in modo che   i controlli delle chiavi esterne possono essere veloci e non   richiede una scansione della tabella. Nel   tabella di riferimento, deve esserci un   indice in cui le colonne chiave esterna   sono elencati come prime colonne in   stesso ordine. Tale indice viene creato   sulla tabella di riferimento automaticamente   se non esiste. (Questo è dentro   in contrasto con alcune versioni precedenti, in   quali indici dovevano essere creati   esplicitamente o la creazione di stranieri   i vincoli chiave fallirebbero).   index_name, se indicato, viene utilizzato come   descritto in precedenza.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top