Perché è importante il modello relazionale per un database?


61

Mi sto avvicinando a un progetto in cui dovrò implementare un database con il mio capo; siamo una startup molto piccola, quindi l'ambiente di lavoro è profondamente personale.

Mi aveva già fornito uno dei database dell'azienda e andava completamente contro ciò che mi era stato insegnato (e letto) a scuola per RDBMS. Ad esempio, ci sono interi database qui costituiti da una tabella (per database indipendente). Una di quelle tabelle è lunga più di 20 colonne e per il contesto, ecco alcuni dei nomi delle colonne di una tabella:

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

Il punto è che dove dovrebbe avere singole tabelle che contengono i dati dell'entità (nome, dimensione, data di acquisto, ecc.), Inserisce tutto in una grande tabella per database.

Voglio migliorare questo design, ma non sono sicuro del motivo per cui un modello di dati adeguatamente normalizzato e segmentato potrebbe effettivamente migliorare questo prodotto. Mentre ho familiarità con la progettazione di database del college e capisco come farlo, non sono sicuro del perché questo effettivamente migliora i database.

Perché un buon schema relazionale migliora un database?


33
Una sola parola: normalizzazione.
Robert Harvey,

9
Elettore vicino - giustificati! :-)
Robbie Dee,

6
È comune per i nuovi dipendenti criticare le procedure stabilite senza comprenderne le ragioni, anche se tali ragioni non sono tecnicamente valide. Per prima cosa scopri perché il tuo capo l'ha costruita in questo modo. Potrebbe sapere che non è un buon design, ma non ha le conoscenze (o più probabilmente, il tempo) per farlo meglio. Eventuali modifiche proposte verranno probabilmente ricevute in modo più positivo se si riconoscono rispettosamente le ragioni del progetto attuale.
Pedro,

5
He [the boss] had given me one of his databases before and it completely went against what I was taught (and read about) in school for RDBMS<- Benvenuti nel mondo reale!
Möoz,

5
Mi viene in mente la mia citazione preferita del database relazionale: "Normalizza fino a quando fa male, denormalizza fino a quando funziona"
Jake

Risposte:


70

L'argomento delle prestazioni è generalmente quello più intuitivo. In particolare, vuoi sottolineare come sarà difficile aggiungere buoni indici in un database non correttamente normalizzato (nota: ci sono casi limite in cui la denormalizzazione può effettivamente migliorare le prestazioni, ma quando entrambi non avete esperienza con i database relazionali probabilmente non sarete facilmente vedi questi casi).

Un altro è l'argomento della dimensione della memoria. Una tabella denormalizzata con molti licenziamenti richiederà molta più memoria. Ciò influisce anche sull'aspetto delle prestazioni: più dati hai, più lente saranno le tue query.

C'è anche un argomento che è un po 'più difficile da capire, ma in realtà è più importante perché non puoi risolverlo lanciando più hardware. Questo è il problema della coerenza dei dati. Un database correttamente normalizzato farà in modo che un prodotto con un ID specifico abbia sempre lo stesso nome. Ma in un database denormalizzato tali incoerenze sono possibili, quindi è necessario prestare particolare attenzione quando si tratta di evitare incoerenze, che impiegherà tempo a programmare per essere corretto e causerà comunque bug che ti costeranno nella soddisfazione del cliente.


19
Un importante caso limite per la denormalizzazione è il data warehousing , in particolare se si dispone di una grande quantità di dati che è garantita che non cambieranno mai e si desidera interrogarli in modo più rapido ed efficiente a spese dello spazio di archiviazione. Buona risposta, questa è solo una FYI per i neofiti di SQL che non sono sicuri del motivo per cui sarebbe desiderabile qualcosa di diverso da 3NF.


11
Non sono sicuro del motivo per cui l'argomento della coerenza è "più difficile da capire". Mi sembra molto più semplice: se un valore cambia, allora tutte le copie di quel valore devono essere aggiornate. L'aggiornamento di una singola copia è molto meno soggetto a errori rispetto all'aggiornamento di centinaia o migliaia di copie degli stessi dati. Ciò vale anche per le relazioni tra i dati. (Se la relazione è memorizzata in due modi, devo aggiornare entrambe le copie della relazione.) Questo è un problema estremamente comune nei DB denormalizzati; in pratica è molto difficile prevenire questa corruzione (un'eccezione è l'utilizzo materializzato del tipo di vista).
jpmc26,

4
L'ultimo paragrafo dovrebbe essere evidenziato in grassetto. :-) Senza la normalizzazione è impossibile garantire l'integrità dei dati. Il controllo dell'input esclusivamente a livello di business logic è una follia, dato che ogni database non normalizzato presenta alla fine una sorta di anomalia dei dati.
DanK,

2
@IsmaelMiguel La pratica abituale è che i dati master come questo non vengano mai cancellati dal database. Lo elimini solo soft impostando un flag su di esso che dice che non è più disponibile. In questo caso particolare sarebbe una buona idea avere una relazione di chiave esterna tra prodotti e ordini, il che significa che il database genererà un errore quando si tenta di eliminare un prodotto a cui fa riferimento qualsiasi ordine.
Philipp,

24

Dovrò implementare un database con il mio capo ...

L'uso di un software di gestione di database dedicato potrebbe essere notevolmente più semplice (scusa, non ho resistito).

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

Se questo database si preoccupa solo di "registrare" quale prodotto è stato venduto dove, quando e da chi, si potrebbe essere in grado di estendere la definizione di "database OK" abbastanza da coprirlo. Se questi dati vengono utilizzati per qualsiasi altra cosa , sono davvero piuttosto scadenti.

Ma ...

L'applicazione / le query che utilizzano questi dati rispondono male / lentamente? Altrimenti, non c'è nessun vero problema da risolvere. Certo, sembra e si sente brutto, ma se funziona, non otterrai alcun "punto" per suggerire che "potrebbe" essere migliore.

Se riesci a trovare sintomi definiti (cioè problemi) che sembrano essere causati da una modellizzazione dei dati scadente, allora prototipi una soluzione migliore. Prendi una copia di uno di questi "database", normalizza i dati e verifica se la tua soluzione funziona meglio. Se è molto meglio (e vorrei aspetto che eventuali operazioni di aggiornamento su questi dati sarebbe massicciamente migliorato) poi tornare al tuo capo e mostrare loro il miglioramento.

È perfettamente possibile ricreare la sua "vista a tabella singola" dei dati con ... beh ... Viste.


11
La resistenza alla singola tabella weltanschauung viene spesso da quelli inesperti con SQL che non comprendono i join, soprattutto per quanto riguarda i dati mancanti, ovvero i join esterni.
Robbie Dee,

6
@RobbieDee Più comunemente, proviene da persone che hanno visto i dati denormalizzati essere danneggiati diventando incoerenti. Sono una di queste persone. Considererei questo tipo di struttura solo nella situazione suggerita da Phill: si tratta di una sorta di tabella di registrazione / reporting in cui i dati non verranno mai aggiornati o aggiornati solo se cancellati e completamente derivati ​​da altre fonti.
jpmc26,

2
Anche se l'applicazione funziona in modo accettabile con un database come questo, non è ancora flessibile come un database correttamente normalizzato. Se il nome del negozio o il nome dell'azienda cambiano, dovrà essere aggiornato ovunque, anziché in un solo negozio o tabella aziendale. In alcuni casi, potrebbe essere quello che desideri (ad esempio se i dati vengono raccolti principalmente per scopi di archiviazione), ma dovremmo sapere di più sulla specifica applicazione.
Zach Lipton,

1
@Zach: d'accordo, ecco perché il registro delle vendite è potenzialmente un caso accettabile per questo. Supponendo che si desideri associare ogni vendita a qualsiasi nome del negozio al momento della vendita, non "il nome corrente del negozio", quindi tentare di "normalizzare" ciò introduce una notevole complessità (perché la tabella che registra i nomi dei negozi dovrebbe essere una serie nel tempo, non solo un valore per storeid)
Steve Jessop,

Forse una regola empirica sarebbe che se l'unica complessità introdotta da una proposta di normalizzazione è che alcune query ora hanno bisogno di join in esse per raccogliere tutte le colonne di cui hanno bisogno per riportare, allora dovresti correre per non camminare per fare quel cambiamento: - )
Steve Jessop,

14

Perché un buon schema relazionale migliora un database?

La risposta è: non migliora sempre un database. Dovresti essere consapevole che ciò che probabilmente ti è stato insegnato è chiamato Terza Forma Normale .

Altri moduli sono validi in alcune situazioni, che è la chiave per rispondere alla tua domanda. Il tuo esempio assomiglia alla prima forma normale , se ciò ti aiuta a sentirti meglio riguardo al suo stato attuale.

Le regole 3NF stabiliscono relazioni tra i dati che "migliorano" un database:

  1. Impedisci l'ingresso di dati non validi nel tuo sistema (se una relazione è 1-a-1, forza un errore nonostante il codice scritto sopra di esso). Se i dati sono coerenti nel database, è meno probabile che si verifichino incoerenze al di fuori del database.

  2. Fornisce un modo per convalidare il codice (ad es. Una relazione molti-a-uno è un segnale per limitare le proprietà / i comportamenti di un oggetto). Quando si scrive codice per utilizzare il database, a volte i programmatori notano la struttura dei dati come indicatore del funzionamento del proprio codice. Oppure possono fornire un feedback utile se il database non corrisponde al loro codice. (Questo è più come un pio desiderio, sfortunatamente.)

  3. Fornire regole che possono aiutare in modo significativo a ridurre gli errori durante la creazione di un database, in modo da non costruirlo in base a requisiti arbitrari che potrebbero verificarsi in qualsiasi momento durante la vita di un database. Invece, stai valutando sistematicamente le informazioni per raggiungere obiettivi specifici.

  4. Strutture di database adeguate portano a prestazioni migliori collegando i dati in modo da ridurre al minimo l'archiviazione dei dati, ridurre al minimo le chiamate di archiviazione per recuperare i dati, massimizzare le risorse in memoria e / o minimizzare l'ordinamento / manipolazione dei dati per il set di dati specifico che hai, rispetto alla query che sei eseguendo contro di esso. Ma la struttura "corretta" dipende dalla quantità di dati, dalla natura dei dati, dal tipo di query, dalle risorse di sistema, ecc. La normalizzazione può peggiorare le prestazioni (ad esempio se si caricano tutti i dati come 1 tabella - l'unione può rallentare una domanda). L'elaborazione delle transazioni (OLTP) rispetto alla business intelligence (data warehouse) sono molto diverse.

In una piccola azienda con piccoli set di dati, potresti scoprire che non c'è nulla di sbagliato nel modo in cui è ora. Tranne che se cresci, sarà difficile "aggiustare" più tardi, perché man mano che la tabella diventa grande, i sistemi che la usano probabilmente rallenteranno.

Di solito vorrai sottolineare le transazioni veloci man mano che un'azienda cresce. Tuttavia, se dedichi tempo a questo progetto ora invece di altre cose di cui la società potrebbe aver bisogno più urgentemente, potresti non avere mai quel problema perché la tua azienda non cresce mai veramente. Questa è la "sfida pre-ottimizzazione" - dove trascorrere il tuo tempo prezioso in questo momento.

In bocca al lupo!


4
Non menzionato, ma penso che un punto importante per i programmatori sia che la modifica di una "cosa" richiede la modifica di una sola riga anziché dover eseguire il ciclo dell'intero database per trovare e sostituire quella singola cosa.
slebetman,

@slebetman Non dovresti mai avere un ciclo lato codice per aggiornare più righe in una singola tabella, indipendentemente dal fatto che sia normalizzato. Usa una WHEREclausola. Naturalmente, questi possono ancora andare storti, ma è meno probabile in una situazione normalizzata poiché devi abbinare solo una riga tramite chiave primaria.
jpmc26,

@ jpmc26: ciclando il database intendo costruire una query per aggiornare tutte le righe interessate. A volte basta un singolo WHERE. Ma ho visto strutture poco profonde che richiedono sottoselezioni nella stessa tabella per ottenere tutte le righe interessate senza influire sulle righe che non dovrebbero cambiare. Ho anche visto strutture in cui una singola query non può svolgere il lavoro (l'entità che deve essere modificata risiede in colonne diverse a seconda della riga)
slebetman

Molte risposte eccellenti a questa domanda, e questa non ha fatto eccezione.
Mike Chamberlain,

11

Ci sono molte ragioni per cui usare una grande "divina tabella" è male. Proverò ad illustrare i problemi con un database di esempio composto. Supponiamo che tu stia cercando di modellare eventi sportivi. Diremo che vuoi modellare i giochi e le squadre che giocano in quei giochi. Un design con più tabelle potrebbe apparire così (questo è molto semplicistico di proposito, quindi non lasciarti sorprendere in luoghi in cui potrebbe essere applicata più normalizzazione):

Teams
Id | Name | HomeCity

Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location

e un unico database di tabelle sarebbe simile a questo

TeamsAndGames
Id | TeamName | TeamHomeCity | GameStartsAt | GameHomeTeamId | GameAwayTeamId | Location

Innanzitutto, diamo un'occhiata a come creare indici su quelle tabelle. Se avessi bisogno di un indice nella città natale per una squadra, potrei aggiungerlo facilmente al Teamstavolo o al TeamsAndGamestavolo. Ricorda che ogni volta che crei un indice, questo deve essere archiviato sul disco da qualche parte e aggiornato come le righe vengono aggiunte alla tabella. Nel caso del Teamstavolo questo è piuttosto semplice. Ho inserito un nuovo team, il database aggiorna l'indice. Ma che dire di TeamsAndGames? Bene, lo stesso vale per ilTeamsesempio. Aggiungo una squadra, l'indice viene aggiornato. Ma succede anche quando aggiungo un gioco! Anche se quel campo sarà nullo per un gioco, l'indice deve comunque essere aggiornato e archiviato su disco per quel gioco. Per un indice, questo non suona troppo male. Ma quando hai bisogno di molti indici per le molteplici entità stipate in questa tabella, perdi molto spazio nella memorizzazione degli indici e un sacco di tempo del processore per aggiornarli per cose in cui non si applicano.

In secondo luogo, coerenza dei dati. Nel caso di usare due tavoli separati, posso usare le chiavi esterne dal Gamestavolo al Teamstavolo per definire quali squadre stanno giocando in una partita. E supponendo che renda le colonne HomeTeamIde AwayTeamIdnon annullabili, il database assicurerà che ogni partita che inserisco abbia 2 squadre e che quelle squadre esistano nel mio database. Ma per quanto riguarda lo scenario a tabella singola? Bene, poiché ci sono più entità in questa tabella, quelle colonne dovrebbero essere nullable (potresti renderle non nullable e inserire dati spazzatura lì, ma questa è solo un'idea orribile). Se quelle colonne sono nullable, il database non può più garantire che quando si inserisce una partita abbia due squadre.

E se decidessi di provarci comunque? Le chiavi esterne vengono impostate in modo tale che quei campi rimandino a un'altra entità nella stessa tabella. Ma ora il database si assicurerà solo che quelle entità esistano nella tabella, non che siano del tipo corretto. Potresti facilmente impostare GameHomeTeamIdl'ID di un altro gioco e il database non si lamenterà affatto. Se lo provaste in uno scenario con più tabelle, il database si adatta.

Puoi provare a mitigare questi problemi dicendo "beh, ci assicureremo solo di non farlo mai nel codice". Se sei sicuro della tua capacità di scrivere codice privo di bug per la prima volta e della tua capacità di prendere in considerazione ogni strana combinazione di cose che un utente potrebbe provare, vai avanti. Personalmente non sono sicuro della mia capacità di fare una di queste cose, quindi lascerò che il database mi dia una rete di sicurezza extra.

(Questo peggiora anche se il tuo progetto è quello in cui copi tutti i dati rilevanti tra le righe invece di usare chiavi esterne. Qualsiasi ortografia / altre incongruenze di dati saranno difficili da risolvere. Come puoi sapere se "Jon" è un errore di ortografia di "John "o se fosse intenzionale (perché sono due persone separate)?)

Terzo, quasi ogni colonna deve essere nullable o deve essere riempita con dati copiati o spazzatura. Un gioco non ha bisogno di un TeamNameo TeamHomeCity. Quindi o ogni gioco ha bisogno di qualche tipo di segnaposto o deve essere nullable. E se è nullable, il database farà felicemente una partita senza TeamName. Ci vorrà anche una squadra senza nome, anche se la tua logica aziendale dice che non dovrebbe mai accadere.

Ci sono una serie di altri motivi per cui vorresti tabelle separate (inclusa la conservazione della sanità mentale degli sviluppatori). Ci sono anche alcuni motivi per cui una tabella più grande potrebbe essere migliore (la denormalizzazione a volte migliora le prestazioni). Questi scenari sono pochi e lontani tra loro (e di solito sono meglio gestiti quando si hanno metriche delle prestazioni per mostrare che questo è davvero il problema, non un indice mancante o qualcos'altro).

Infine, sviluppa qualcosa che sarà facile da mantenere. Solo perché "funziona" non significa che sia OK. Cercare di mantenere le tabelle degli dei (come le classi degli dei) è un incubo. Ti stai solo preparando per il dolore più tardi.


1
"Squadre: ID | Nome | HomeCity". Assicurati solo che il tuo schema di dati non faccia in modo errato che la tua domanda affermi che il Super Bowl XXXIV è stato vinto da LA Rams. Mentre SB XXXIV dovrebbe apparire in una query per tutti i campionati vinti dalla squadra attualmente conosciuta come LA Rams. Ci sono "tavoli divini" migliori e peggiori, e sicuramente ne hai presentato uno cattivo. Uno migliore sarebbe "ID gioco | nome della squadra di casa | città della squadra di casa | nome della squadra ospite | città della squadra ospite | il gioco inizia alle | ecc ...". Che nasce come primo tentativo di modellare informazioni come "New Orleans Saints @ Chicago Bears 1p Eastern".
Steve Jessop,

6

Citazione del giorno: " Teoria e pratica dovrebbero essere le stesse ... in teoria "

Tavolo denormalizzato

La tua unica tabella contiene tutti i dati ridondanti ha un vantaggio: rende il reporting sulle sue righe molto semplice da codificare e veloce da eseguire perché non è necessario eseguire alcun join. Ma questo ad un costo elevato:

  • Contiene copie ridondanti delle relazioni (ad es. IngCompanyIDE vrCompanyName). L'aggiornamento dei dati anagrafici potrebbe richiedere l'aggiornamento di molte più righe rispetto a uno schema normalizzato.
  • Mescola tutto. Non è possibile garantire un facile controllo di accesso a livello di database, ad esempio garantendo che l'utente A possa aggiornare solo le informazioni sull'azienda e l'utente B solo le informazioni sul prodotto.
  • Non è possibile garantire regole di coerenza a livello di database (ad es. Chiave primaria per imporre che esiste un solo nome di società per un ID di società).
  • Non si beneficia appieno dell'ottimizzatore DB che potrebbe identificare strategie di accesso ottimali per una query complessa, sfruttando le dimensioni delle tabelle normalizzate e le statistiche di diversi indici. Ciò potrebbe compensare rapidamente il vantaggio limitato di evitare i join.

Tavolo normalizzato

Gli svantaggi di cui sopra sono vantaggi per lo schema normalizzato. Naturalmente, le query potrebbero essere un po 'più complesse da scrivere.

In breve, lo schema normalizzato esprime molto meglio la struttura e le relazioni tra i tuoi dati. Sarò provocatorio e dirò che è lo stesso tipo di differenza tra la disciplina richiesta per usare un set di cassetti per ufficio ordinati e la facilità d'uso di un cestino.


5

Penso che ci siano almeno due parti alla tua domanda:

1. Perché entità di tipi diversi non dovrebbero essere archiviate nella stessa tabella?

Le risposte più importanti qui sono la leggibilità e la velocità del codice. A SELECT name FROM companies WHERE id = ?è molto più leggibile di a SELECT companyName FROM masterTable WHERE companyId = ?e si ha meno probabilità di interrogare accidentalmente assurdità (ad es. SELECT companyName FROM masterTable WHERE employeeId = ?Non sarebbe possibile quando società e dipendenti sono archiviati in tabelle diverse). Per quanto riguarda la velocità, i dati da una tabella del database vengono recuperati leggendo la tabella completa in sequenza o leggendo da un indice. Entrambi sono più veloci se la tabella / indice contiene meno dati, e questo è il caso se i dati sono memorizzati in tabelle diverse (e devi solo leggere una delle tabelle / indici).

2. Perché le entità di un singolo tipo devono essere suddivise in entità secondarie archiviate in tabelle diverse?

Qui, il motivo è principalmente quello di prevenire incoerenze nei dati. Con l'approccio a tabella singola, per un sistema di gestione degli ordini è possibile memorizzare il nome cliente, l'indirizzo cliente e l'ID prodotto del prodotto ordinato dal cliente come singola entità. Se un cliente ordinasse più prodotti, nel tuo database avresti più istanze del nome e dell'indirizzo del cliente. Nel migliore dei casi, hai appena ottenuto dati duplicati nel tuo database, che potrebbero rallentarli un po '. Ma un caso peggiore è che qualcuno (o qualche codice) ha commesso un errore quando i dati sono stati inseriti in modo che una società finisca con indirizzi diversi nel database. Questo da solo è abbastanza male. Ma se dovessi interrogare l'indirizzo di un'azienda in base al suo nome (esSELECT companyAddress FROM orders WHERE companyName = ? LIMIT 1) otterresti restituito arbitrariamente uno dei due indirizzi e non ti accorgeresti nemmeno che ci sia stata un'incoerenza. Ma ogni volta che esegui la query potresti effettivamente ottenere un indirizzo diverso, a seconda di come la query viene risolta internamente dal DBMS. Ciò probabilmente interromperà l'applicazione da qualche altra parte e la causa principale di tale interruzione sarà molto difficile da trovare.

Con l'approccio multi-tabella, ti accorgeresti che esiste una dipendenza funzionale dal nome dell'azienda all'indirizzo della società (se una società può avere un solo indirizzo), memorizzeresti la tupla (companyName, companyAddress) in una tabella (ad es. company) e la tupla (productId, companyName) in un'altra tabella (ad es order.). Un UNIQUEvincolo sulla companytabella potrebbe quindi imporre che ogni azienda abbia un solo indirizzo nel database in modo che non possa mai sorgere un'incoerenza per gli indirizzi dell'azienda.

Nota: in pratica, per motivi di prestazioni probabilmente genereresti un ID azienda unico per ogni azienda e lo utilizzeresti come chiave esterna invece di utilizzare direttamente companyName. Ma l'approccio generale rimane lo stesso.


3

TL; DR - Stanno progettando il database in base a come sono stati insegnati quando erano a scuola.

Avrei potuto scrivere questa domanda 10 anni fa. Mi ci è voluto del tempo per capire perché i miei predecessori progettassero i loro database come facevano loro. Stai lavorando con qualcuno che:

  1. Ha acquisito la maggior parte delle competenze di progettazione del database utilizzando Excel come database o
  2. Stanno usando le migliori pratiche da quando sono usciti da scuola.

Non sospetto che sia il numero 1 dato che in realtà ci sono numeri ID nella tua tabella, quindi assumerò il numero 2.

Dopo essere uscito da scuola, lavoravo in un negozio che utilizzava un AS / 400 (aka IBM i). Ho trovato alcune cose strane nel modo in cui hanno progettato i loro database e ho iniziato a sostenere che apportiamo modifiche per seguire come mi è stato insegnato come progettare i database. (Ero stupido allora)

Ci è voluto un programmatore paziente più vecchio per spiegarmi perché le cose fossero state fatte in quel modo. Non avevano modificato lo schema perché avrebbe causato la rottura dei programmi più vecchi di me. Letteralmente, il codice sorgente di un programma aveva una data di creazione dell'anno prima che io nascessi. Sul sistema su cui stavamo lavorando, i loro programmi dovevano implementare tutta la logica e le operazioni che il planner di query del database gestisce per te. (Puoi vederlo eseguendo EXPLAIN su una delle tue query)

Era aggiornato sulle tecniche che stavo cercando di implementare, ma mantenere il sistema in esecuzione era più importante che apportare modifiche "perché andava contro ciò che mi era stato insegnato". Ogni nuovo progetto che uno di noi ha iniziato ha fatto il miglior uso del modello relazionale che siamo stati in grado di fare. Sfortunatamente, altri programmatori / consulenti di quel periodo progettavano ancora i loro database come se stessero lavorando con i vincoli precedenti di quel sistema.


Alcuni esempi di ciò che ho riscontrato che non si adattava al modello relazionale:

  • Le date venivano memorizzate come numeri del giorno giuliano che richiedevano un join a una tabella delle date per ottenere la data effettiva.
  • Tabelle denormalizzate con colonne sequenziali dello stesso tipo (ad es. code1,code2, ..., code20)
  • Lunghezza NxM colonne CHAR che rappresentano una matrice di N stringhe di lunghezza M.

Le ragioni che mi sono state date per quelle decisioni di progettazione erano tutte basate sui vincoli del sistema quando il database è stato progettato per la prima volta.

Date - Mi è stato detto che ci voleva più tempo di elaborazione per utilizzare le funzioni di data (quale mese o giorno o giorno della settimana) per elaborare una data rispetto a quanto ha fatto per creare una tabella di ogni data possibile con tutte quelle informazioni.

Colonne sequenziali dello stesso tipo : l'ambiente di programmazione in cui si trovavano consentiva a un programma di creare una variabile array su parte della riga. Ed è stato un modo più semplice per ridurre il numero di operazioni di lettura.

Colonne CHAR lunghezza NxM : è stato più semplice inserire i valori di configurazione in una colonna per ridurre le operazioni di lettura dei file.

Un esempio mal concepito in equivalente C per riflettere l'ambiente di programmazione che avevano:

#define COURSE_LENGTH 4
#define NUM_COURSES 4
#define PERIOD_LENGTH 2

struct mytable {
    int id;
    char periodNames[NUM_COURSES * PERIOD_LENGTH];  // NxM CHAR Column
    char course1[COURSE_LENGTH];
    char course2[COURSE_LENGTH];
    char course3[COURSE_LENGTH];
    char course4[COURSE_LENGTH];
};

...

// Example row
struct mytable row = {.id= 1, .periodNames="HRP1P2P8", .course1="MATH", .course2="ENGL", .course3 = "SCI ", .course4 = "READ"};

char *courses; // Pointer used to access the sequential columns
courses = (char *)&row.course1;


for(int i = 0; i < NUM_COURSES; i++) {

    printf("%d: %.*s -> %.*s\n",i+1, PERIOD_LENGTH, &row.periodNames[PERIOD_LENGTH * i], COURSE_LENGTH,&courses[COURSE_LENGTH*i]);
}

Uscite

1: HR -> MATH
2: P1 -> ENGL
3: P2 -> SCI
4: P8 -> LEGGI

Secondo quanto mi è stato detto, alcune di queste erano considerate le migliori pratiche al momento.

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.