Qual è il miglior schema del database per supportare valori che sono appropriati solo per righe specifiche?

Ho una tabella di db chiamata Calendario con campi

  1. Id (PK)
  2. Nome
  3. Descrizione
  4. CalendarTypeId (FK nella tabella CalendarType )

Ho un’altra tabella chiamata CalendarType con i campi

  1. Id (PK)
  2. Nome
  3. Descrizione

Il problema è che ho bisogno di memorizzare un campo aggiuntivo per ogni calendario in cui il tipo di calendario è 2. (ma questo campo sarebbe irrilevante per qualsiasi altro tipo di calendario).

Dovrei semplicemente creare un nuovo campo nella tabella Calendario e ignorare quel campo per tutti gli altri calendari che hanno un diverso calendarioTypeid o esiste un modo migliore per organizzare questo schema per supportare questa esigenza.

    Ok, questo è il modello ER di ciò che hai attualmente (omettendo le cardinalità):

    Ora concentriamoci su Calendar e SubCalendar. Chiaramente, hai una gerarchia lì. Ma come si trasformano le gerarchie in tabelle? Ci sono tre modi comuni per farlo:

    1) Uccidi il genitore e tieni i bambini : in questo caso rimuovi l’entity framework genitore e mandi tutti i campi da quell’ quadro a ciascuno dei bambini. Nel tuo esempio hai solo un figlio, quindi tutti gli attributi del genitore andranno solo ad esso.

    Vantaggi : Nessun valore null poiché ogni tabella avrà tutto ciò di cui ha bisogno. Neanche i join sono richiesti. Se eseguirai query per la ricerca di un solo tipo di bambino, questo schema sarà utile perché non dovrai filtrare per tipo perché ogni tabella memorizzerà solo un tipo

    Svantaggi : questo schema non è appropriato per i casi in cui si hanno bambini sovrapposti. In altre parole, se una riga genitore può avere più di un figlio quando invia i campi a ciascun figlio, i dati genitore saranno duplicati in ogni bambino. Non va bene, quindi non usare questa strategia se questo è il caso. Inoltre, se hai molti figli e pochi record in ognuno, avrai molte tabelle con pochi record ciascuno, quindi potrebbe diventare un po ‘più difficile da gestire

    2) Uccidi i bambini e mantieni il genitore : in questo caso rimuovi tutti i bambini e invii tutti i loro attributi al genitore. Poiché il genitore ora è un mix di se stesso e di tutti i suoi figli, ha bisogno di un modo per determinare quale riga appartiene a quale tipo di bambini. Ciò si ottiene aggiungendo un nuovo attributo all’ quadro padre che determinerà il tipo di ogni riga (indipendentemente dal tipo di dati).

    Vantaggi : ci sarà solo un tavolo per tutti i bambini, quindi è facile da gestire. Non sono richiesti join. Potrebbe essere utile se la maggior parte delle query eseguite su questa tabella richiede risultati da più di un tipo di bambini.

    Svantaggi : ancora una volta, se un genitore può avere una riga che si riferisce a più di un bambino, i dati saranno duplicati in quanto ci sarà una riga per ciascuno di essi, quindi c’è una limitazione in questa soluzione. Inoltre, una nuova colonna dovrà essere aggiunta come metadata. Il volume dei record nella tabella sarà il più grande. I valori nulli dovranno essere assegnati ai dati che i bambini hanno e il genitore o altri bambini hanno.

    3) Mantieni tutto : la soluzione meno sanguinosa non è quella di uccidere nulla 🙂 In questo caso la gerarchia viene sostituita da una relazione tra il genitore e ciascuno dei bambini. In questo modo, un bambino dovrà unirsi alla tabella genitore per mezzo di una chiave esterna per raggiungere i dati del genitore.

    Vantaggi : non vi è alcuna duplicazione dati né valori nulli. Ogni entity framework ha solo la quantità minima di dati e il resto può essere ottenuto unendosi alla tabella padre. In questo caso, una riga padre può essere collegata a più di un bambino senza duplicare i dati. Se verranno eseguite molte query che possono essere soddisfatte con una sola tabella (di solito quella principale), questa è una buona opzione. Un’altra cosa è che è facile estendere a più calendari, ad esempio, se è necessario aggiungere un nuovo calendario che richiede nuovi campi, allora è necessario aggiungere una nuova tabella, senza modificare quelli correnti

    Svantaggi : richiede il maggior numero di tavoli (in realtà uno in più rispetto al primo). È necessario un join per ogni bambino che degraderà le prestazioni, maggiore diventa il dataset. Inoltre, saranno necessarie chiavi esterne per partecipare a entrambe le tabelle. Se la maggior parte delle query richiederà dati da genitori e figli, questo schema sarà il peggiore in termini di prestazioni

    Ora, hai chiesto qual è il best schema del database. Penso che ora sia chiaro che dipende dai requisiti, dai tipi di query che verranno eseguiti, dal modo in cui i dati sono strutturati, ecc.

    Tuttavia, posso analizzare questo un po ‘di più. Hai detto che avevi una tabella di Calendar e talvolta sono necessari più dati per uno di essi. Quindi possiamo dire che abbiamo 2 tipi di calendari, il genitore e il bambino. Quindi potremmo pensare che optare per la soluzione 2 sia una buona possibilità perché avrete 2 righe che rappresentano ciascun tipo, ma saremmo in errore. Questo perché ogni bambino include il suo genitore in questo caso. Ora, se possiamo supporre che se SubAttribute sarà sempre non nullo per un figlio e null per un genitore possiamo anche rimuovere CalendarType , che in realtà porterà alla soluzione 1.

    Infine, come regola generale (e soprattutto perché la maggior parte delle query ha molti join nella vita reale), se vuoi concentrarti sulle prestazioni, dovresti optare per la soluzione 1, altrimenti, se vuoi concentrarti sul design normalizzato, dovresti vai per la soluzione 3.

    Spero che questo abbia chiarito alcuni dubbi e possibilmente generato altri 🙂

    Probabilmente userò Calendar. Lo chiamo sovraccarico della tabella Db. Quando la conservazione dei dati era costosa, questo era un crimine. Ora si chiama risolvere il problema nel modo più semplice e andare avanti. Mai sopra l’ingegnere fino a quando non ne hai davvero bisogno.

    Tuttavia, non hai specificato esplicitamente se il valore del campo extra variava per ogni istanza di Calendar con un typeID di 2. A volte le mie tabelle Type hanno campi di sottotipo, ecc., Ma suppongo che sia il caso in cui le istanze di Calendar di Tipo 2 Avrà valori diversi nel campo richiesto.

    Forse sto guardando troppo semplicemente questo, ma se ti attieni al modello di “usa prima di riutilizzare” la cosa giusta da fare è semplicemente aggiungere la colonna null-able alla tua tabella di calendario e aggiungere un vincolo di controllo al tipo di calendario assicurandoti che non sia nullo se il tipo di calendario è = 2.

    È semplice e soprattutto è facilmente verificabile.

    Potrei ottenere un po ‘di flessibilità per questa risposta (probabilmente non la più efficiente), ma dipende completamente dalla scala della soluzione. La realtà è che questi vincoli potrebbero cambiare molto nei prossimi due mesi e non si vuole dipingere in un angolo scegliendo il modo “giusto” quando non si sa ancora quale sia. È del tutto ansible che quando arrivi al decimo tipo di calendario apparirà un modello che ti dirà il modo migliore (o il più normale) per farlo. Per ora, mantienilo semplice e rendilo facile da testare e facile da cambiare in seguito.

    Puoi utilizzare il modello di ereditarietà a tabella singola, che è vicino al tuo suggerimento,

    http://martinfowler.com/eaaCatalog/singleTableInheritance.html

    o

    http://martinfowler.com/eaaCatalog/classTableInheritance.html

    se vuoi specializzare alcune tabelle per abbinare i tipi (Calendar e CalendarType2) che stai cercando di rappresentare nel tuo database

    Leora,

    Ti consigliamo di utilizzare la tabella del calendario e annullare i campi aggiuntivi non necessari per gli altri tipi di calendario. A mano a mano che i requisiti cambiano, sarai in grado di aggiungere più attributi alla tabella del calendario in questo modo.

    Raccomando anche di avere una class di calendario di base per il modello, quindi creare sottoclassi mappate utilizzando il campo calendartypeid e utilizzare le sottoclassi di calendario specifiche all’interno dell’applicazione come richiesto. La maggior parte delle ORMS supporterà questo tipo di mapping e ti consentirà anche di rendere ogni sottoclass diversa dalle altre, se necessario

    Stefano