tabella singola con colonne aggiuntive rispetto a più tabelle che duplicano lo schema

8

Sto lavorando a un progetto in cui, a un certo punto, dovevo prendere una decisione sull'opportunità o meno, nel database, di avere una singola tabella con più colonne non utilizzate da ogni record o più tabelle con schema duplicato .

Sto creando un'applicazione di informazioni sportive in grado di gestire più attività sportive. Ad esempio, possiamo gestire NBA, NHL, MLB, NFL. Ogni sport ha concetti molto simili: squadre, orari, infortuni, informazioni sul giocatore ..

Naturalmente, la nostra fonte di dati non ci fornisce tutti i dati nello stesso schema. Ogni sport ha uno schema diverso a cui riceviamo i dati dal nostro fornitore.

Dato che non c'era abbastanza tempo (richieste dei clienti) per fare un'analisi anticipata dei feed di dati per determinare gli elementi comuni, ho coperto la mia scommessa e ho preso la "scommessa sicura" e ho creato tabelle separate per ogni sport invece di una serie di tavoli usati da tutti gli sport.

Il risultato è uno schema duplicato in diverse tabelle e quindi interfacce duplicate nel database (ad esempio stored proc). Ho qualcosa come NBA_Game, NFL_Game, NBA_Team, NFL_Team, ecc. Ogni tabella potrebbe avere alcune proprietà che l'altra non ha, e molte che sono condivise. va avanti per dire 5-10 tavoli in 4 o 5 sport. Non sono ancora sicuro che sia una cosa del tutto negativa - l'alternativa, avendo un solo set di tabelle che aveva proprietà su di esso che non tutti gli sport avrebbero usato, potrebbe essere stata di per sé poco maneggevole.

Qualcuno che ha fatto questo si imbatte in insidie di questo tipo di design e potrebbe condividere la sua esperienza qui? Cose che potrebbero aiutarmi a conoscere ora invece di imparare la strada difficile lungo la strada? L'hai fatto in un altro modo, con una grande tabella / serie di tabelle, con colonne che non tutti i record avrebbero usato? Quali sono le insidie in cui ti sei imbattuto in questo?

Esistono alternative come ereditarietà delle tabelle che hai utilizzato in il passato ha funzionato meglio?

Grazie

    
posta dferraro 05.02.2014 - 18:01
fonte

2 risposte

11

In definitiva, si tratta di utilizzo e architettura.

Architettura

Il sistema gestisce "qualsiasi sport"? L'idea che hai messo sul tuo cappello da astronauta di architettura e costruire un sistema generico in grado di gestire qualsiasi tipo futuro di sport che potrebbe non esistere nemmeno oggi?

Se è così, ovviamente avere tabelle con nomi dinamici è un grosso problema, quindi avrebbe senso avere uno schema che supporti gli sport, se necessario.

Detto questo, ho un strong pregiudizio contro questo approccio: questo è quasi sempre più lavoro e porta a risultati più scadenti. Realizzare un'interfaccia utente, uno schema e così via per ogni sport alla fine porterà a una migliore esperienza utente ea un codice di manutenzione più semplice, anche se ciò significa una quantità superficiale di duplicazione (come evitare / minimizzare questa è una domanda separata). p>

Come gestisci i giocatori che praticano sport multipli? Ricevono due voci (ad esempio, trattate come persone diverse) o state cercando di fare qualcosa di specifico con loro?

Usa

Quindi supponiamo di non praticare sport in modo dinamico (ad esempio, se qualcuno vuole aggiungere un nuovo sport, è necessario uno sforzo di sviluppo per aggiungerlo).

C'è sempre un momento in cui stai visualizzando i giocatori (o qualsiasi altro oggetto che hai menzionato) da più di uno sport alla volta?

Potrei vederlo per una funzione di ricerca, dove puoi cercare per nome giocatore o squadra (indipendentemente dallo sport), ma oltre a questo non posso immaginare molti casi d'uso.

Se non hai mai bisogno di farlo, allora il tuo approccio è perfetto. Puoi smettere di leggere qui.

Schemi alternativi

Vista

Sono un fan dei KISS. In oltre 15 anni di sviluppo del software, continuo a ricorrere alla filosofia "costruisci la cosa più semplice che funzioni".

Quindi la mia reazione iniziale, supponendo che una funzione di ricerca tra sport sia davvero l'unico caso d'uso, è creare viste:

SELECT PlayerName, 'NFL' as [Sport], TeamName FROM NFL_Players JOIN NFL_Teams ... 
UNION  
SELECT PlayerName, 'NHL' as [Sport], TeamName FROM NHL_Players JOIN NHL_Teams ... 
UNION ....

Naturalmente, se aggiungi un nuovo sport, devi aggiungere alla vista. Potrebbe anche essere utile includere altre informazioni comuni, ma in realtà dipende da ciò che deve essere mostrato.

Cercherò di mantenere tutte le cose specifiche per lo sport nella definizione View, quindi il codice di ricerca non ha bisogno di avere molto o un codice specifico (oltre forse sapere come collegare a /nhl/players/player-name vs /nfl/... o comunque la tua app lo fa).

Ereditarietà della tabella

L'ereditarietà delle tabelle può funzionare, ma è piuttosto complessa. Non ho un sacco di esperienza con esso, e infatti, penso che ogni volta che sono stato coinvolto nella valutazione, abbiamo finito per fare qualcosa di più semplice (come sto suggerendo qui).

Quindi personalmente, devo ancora scoprire perché sarebbe utile, ma forse c'è un caso d'uso convincente (che non conosco) che giustifica la complessità (ad esempio, l'ereditarietà delle tabelle risolve il caso d'uso meglio di qualsiasi altro altra soluzione).

Tabelle separate per attributi specifici dello sport

Potresti creare una sola tabella players con attributi comuni a tutti i giocatori di tutti gli sport, quindi un altro set di tabelle come nhl_players_details che contiene un PlayerId e colonne con informazioni aggiuntive sul giocatore. Se ci sono una tonnellata di attributi comuni, o hai molti usi di "tutti i giocatori di tutti gli sport", allora questo può avere senso.

Coppie di valori chiave per attributi specifici dello sport

Approccio completamente alternativo: avere una tabella players (di nuovo, con attributi comuni come nome) e poi una tabella player_data che ha PlayerId , Sport , Attribute , Value . I nomi degli attributi inseriti sarebbero specifici per lo sport. Questo ti permette di aggiungere essenzialmente nuovi attributi senza modificare lo schema (il tuo codice dovrebbe ancora sapere di caricarli / visualizzarli ovviamente). Lo svantaggio è che perdi un po 'di integrità: il valore sarebbe in genere un campo stringa, quindi il codice dell'app dovrebbe essere resiliente e gestire potenziali errori che convertono la stringa value in un tipo di dati specifico (come integer).

Questo concetto può ovviamente applicarsi a Teams, Giochi, ecc.

    
risposta data 05.02.2014 - 19:10
fonte
4

Stai parlando di Normalizzazione del database . Potresti essere sollevato nell'apprendere che non esiste un modello di dati perfetto e che una maggiore normalizzazione non è sempre migliore. La normalizzazione può imporre costi in termini di chiarezza del modello di dati e delle prestazioni del database. Pertanto, il modello migliore da selezionare dipenderà dai tuoi requisiti di utilizzo.

Sulla superficie, i tuoi esempi sembrano abbastanza simili nel concetto (X_Game vs Y_Game e X_Team vs Y_Team) che il sovraccarico extra di alcune colonne non sembra irragionevole. Detto questo, se ogni sport aggiungerà diverse decine di colonne in più al tavolo, sarebbe davvero poco pratico.

In questo caso, potresti prendere in considerazione un modello ibrido, in cui i dati comuni sono conservati in una tabella centrale, ma i dati specifici dello sport sono conservati in una struttura di dati collegata. Qualcosa come:

table Game {
    gameId int,
    teamId1 int fk,
    teamId2 int fk
}

table HockeyGame {
    gameId int fk,
    penaltyMinutes int
}

table BasketballGame {
    gameId int fk,
    freeThrows int
}
    
risposta data 05.02.2014 - 19:17
fonte

Leggi altre domande sui tag