Domanda

Nel mio database ho le seguenti tabelle che hanno una relazione molti-a-molti, espressa da una tabella di connessione che ha chiavi esterne per le chiavi primarie di ciascuna delle tabelle principali:

  • Aggeggio:WidgetID (PK), titolo, prezzo
  • Utente:ID utente (PK), nome, cognome

Supponiamo che ogni combinazione utente-widget sia unica.Vedo due opzioni su come strutturare la tabella di connessione che definisce la relazione tra i dati:

  1. Widget utente1:UserWidgetID (PK), WidgetID (FK), UserID (FK)
  2. Widget utente2:ID widget (PK, FK), ID utente (PK, FK)

L'opzione 1 ha una singola colonna per la chiave primaria.Tuttavia, ciò non sembra necessario poiché gli unici dati archiviati nella tabella sono la relazione tra le due tabelle primarie e questa relazione stessa può formare una chiave univoca.Portando così all'opzione 2, che ha una chiave primaria a due colonne, ma perde l'identificatore univoco a una colonna dell'opzione 1.Facoltativamente potrei anche aggiungere un indice univoco a due colonne (WidgetID, UserID) alla prima tabella.

C'è qualche differenza reale tra i due in termini di prestazioni o qualche motivo per preferire un approccio rispetto all'altro per strutturare la tabella molti-a-molti di UserWidgets?

È stato utile?

Soluzione

In entrambi i casi hai solo una chiave primaria.La seconda è quella che viene chiamata chiave composta.Non c'è una buona ragione per introdurre una nuova rubrica.In pratica, dovrai mantenere un indice univoco su tutte le chiavi candidate.L'aggiunta di una nuova colonna non comporta altro che spese generali di manutenzione.

Vai con l'opzione 2.

Altri suggerimenti

Personalmente, io volevo avere la colonna chiave sintetica/surrogata nelle tabelle molti-a-molti per i seguenti motivi:

  • Se hai utilizzato chiavi numeriche sintetiche nelle tabelle delle entità, avere le stesse nelle tabelle delle relazioni mantiene la coerenza nella progettazione e nella convenzione di denominazione.
  • In futuro potrebbe accadere che la stessa tabella molti-a-molti diventi un'entità madre di un'entità subordinata che necessita di un riferimento univoco a una singola riga.
  • In realtà non utilizzerà molto spazio su disco aggiuntivo.

La chiave sintetica non sostituisce la chiave naturale/composta né diventa la chiave PRIMARY KEY per quella tabella solo perché è la prima colonna della tabella, quindi sono parzialmente d'accordo con l'articolo di Josh Berkus.Tuttavia, non sono d'accordo sul fatto che le chiavi naturali siano sempre buoni candidati per PRIMARY KEY's e certamente non dovrebbero essere usati se devono essere usati come chiavi esterne in altre tabelle.

L'opzione 2 utilizza una semplice chiave composta, l'opzione 1 utilizza a chiave surrogata.L'opzione 2 è preferita nella maggior parte degli scenari ed è vicina al modello virtuale in quanto è una buona chiave candidata.

Ci sono situazioni in cui potresti voler utilizzare una chiave surrogata (Opzione 1)

  1. Non sei che la chiave composta sia una buona chiave candidata nel tempo.In particolare con i dati temporali (dati che cambiano nel tempo).Cosa succederebbe se volessi aggiungere un'altra riga alla tabella UserWidget con lo stesso UserId e WidgetId?Pensa all'occupazione(EmployeeId,EmployeeId): funzionerebbe nella maggior parte dei casi, tranne nel caso in cui qualcuno tornasse a lavorare per lo stesso datore di lavoro in un secondo momento
  2. Se stai creando messaggi/transazioni commerciali o qualcosa di simile che richiede una chiave più semplice da utilizzare per l'integrazione.Forse la replica?
  3. Se vuoi creare i tuoi meccanismi di controllo (o simili) e non vuoi che le chiavi diventino troppo lunghe.

Come regola generale, quando modelli i dati scoprirai che la maggior parte delle entità associative (da molti a molti) sono il risultato di un evento.La persona inizia a lavorare, l'articolo viene aggiunto al carrello, ecc.La maggior parte degli eventi ha una dipendenza temporale dall'evento, dove la data o l'ora sono rilevanti, nel qual caso una chiave surrogata potrebbe essere la migliore alternativa.

Quindi, scegli l'opzione 2, ma assicurati di avere il modello completo.

Sono d'accordo con le risposte precedenti ma ho un'osservazione da aggiungere.Se vuoi aggiungere più informazioni alla relazione e consentire più relazioni tra le stesse due entità, hai bisogno dell'opzione uno.

Ad esempio, se desideri tenere traccia di tutte le volte in cui l'utente 1 ha utilizzato il widget 664 nella tabella userwidget, userid e widgetid non sono più univoci.

Qual è il vantaggio di una chiave primaria in questo scenario?Considera l'opzione senza chiave primaria:Widget utente3:ID widget (FK), ID utente (FK)

Se desideri l'unicità, utilizza la chiave composta (UserWidgets2) o un vincolo di unicità.

Il solito vantaggio in termini di prestazioni derivante dall'avere una chiave primaria è che spesso si esegue una query sulla tabella tramite la chiave primaria, il che è veloce.Nel caso di tabelle molti-a-molti di solito non si esegue una query tramite la chiave primaria, quindi non vi è alcun vantaggio in termini di prestazioni.Le tabelle molti-a-molti vengono interrogate in base alle loro chiavi esterne, quindi dovresti prendere in considerazione l'aggiunta di indici su WidgetID e UserID.

L'opzione 2 è la risposta corretta, a meno che tu non abbia un motivo veramente valido per aggiungere un tasto numerico surrogato (cosa che hai fatto nell'opzione 1).

Le colonne di chiavi numeriche surrogate non sono "chiavi primarie".Le chiavi primarie sono tecnicamente una delle combinazioni di colonne che identificano in modo univoco un record all'interno di una tabella.

Chiunque crei un database dovrebbe leggere questo articolo http://it.toolbox.com/blogs/database-soup/primary-keyvil-part-i-7327 di Josh Berkus per comprendere la differenza tra colonne di chiavi numeriche surrogate e chiavi primarie.

Nella mia esperienza, l'unico vero motivo per aggiungere una chiave numerica surrogata alla tabella è se la chiave primaria è una chiave composta e deve essere utilizzata come riferimento di chiave esterna in un'altra tabella.Solo allora dovresti pensare di aggiungere una colonna in più alla tabella.

Ogni volta che vedo una struttura di database in cui ogni tabella ha una colonna "id", è probabile che sia stata progettata da qualcuno che non apprezza il modello relazionale e mostrerà invariabilmente uno o più dei problemi identificati nell'articolo di Josh.

Io andrei con entrambi.

Ascoltami:

La chiave composta è ovviamente il modo carino e corretto per riflettere il significato dei tuoi dati.Nessuna domanda.

Tuttavia:Ho avuto tutti i tipi di problemi nel far funzionare correttamente l'ibernazione a meno che non si utilizzi un'unica chiave primaria generata, una chiave surrogata.

Quindi utilizzerei dati logici e fisici modello.Quello logico ha la chiave composta.Il modello fisico - che implementa il modello logico - ha la chiave surrogata e le chiavi esterne.

Poiché ogni combinazione utente-widget è unica, dovresti rappresentarla nella tua tabella rendendo unica la combinazione.In altre parole, scegli l’opzione 2.Altrimenti potresti avere due voci con lo stesso widget e ID utente ma ID widget utente diversi.

Lo userwidgetid nella prima tabella non è necessario, poiché come hai detto tu l'unicità deriva dalla combinazione di widgetid e userid.

Vorrei utilizzare la seconda tabella, mantenere le chiavi esterne e aggiungere un indice univoco su widgetid e userid.

COSÌ:

userwidgets( widgetid(fk), userid(fk),
             unique_index(widgetid, userid)
)

C'è un certo vantaggio in termini di prestazioni nel non avere la chiave primaria aggiuntiva, poiché il database non avrebbe bisogno di calcolare l'indice per la chiave.Nel modello precedente, tuttavia, questo indice (tramite unique_index) viene ancora calcolato, ma credo che sia più facile da capire.

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