Ho un problema con la progettazione di database (SQL/MySQL). Supponiamo di avere un utente , l'utente può avere molti amici e molti post e riempire alcuni dati su se stesso.Progettazione database - relazioni vs proprietà
E 'abbastanza ovvio che per friends
abbiamo bisogno di un tabella_pivot per n: n relazione, per posts
abbiamo bisogno di creare una tabella in più con user_id (1: n) relazione.
Quindi abbiamo bisogno delle tabelle users
, user_friends
e posts
. Questo è ovvio. Ecco come devono essere gestite le relazioni.
Ma ora supponiamo che vogliamo per gli utenti di avere i seguenti dati:
name - text
description - text
marital status - select only one from list
favourite colour - select only one from list
hobby - select up to 3 from list
Per i campi di testo (nome, descrizione) è davvero ovvio che semplicemente creare colonne varchar/testo in users
tavolo e il gioco è fatto.
La domanda generale è: come devono essere gestiti gli altri campi (scelti dagli elenchi)? Devo creare delle relazioni per loro o forse dovrei creare colonne di dati standard con loro?
Secondo me non ha senso creare tabelle di relazione per questo perché usando le liste (seleziona) limitiamo l'utente solo quando può infatti incollarlo nel database. In teoria potremmo consentire all'utente di inserire manualmente come colore preferito il suo colore (ad esempio red
e se digita qualcosa di sbagliato, ad esempio reds
, confronteremo l'elenco con colours
consentito). Lo stesso sarebbe per il genere - non c'è motivo, secondo me, di creare un tavolo in più quando teniamo solo la donna e l'uomo e creiamo una relazione per esso. disegno
Prima DB:
potrei ad esempio creare le seguenti colonne per le proprietà:
marital_status - int
fav_colour - int
hobby_1 - int
hobby_2 - int
hobby_3 - int
E avere un altro tavolo (o anche di matrice normale in PHP o altra lingua) dove ho negozio che il valore 1 per fav_colour è ad esempio rosso, valore 2 per hobby è musica e così via (non importa come li memorizzi qui - potrei anche usare il tipo enum
per quello).
Per me i vantaggi di tale atteggiamento non creano molte relazioni che sono in realtà proprietà e non relazioni (come ho detto sopra), quindi meno lavoro + più facile ottenere informazioni sull'utente - non è necessario utilizzare alcun join cosa sarebbe importante se si ha per l'utente per esempio 20 o 100 tali proprietà e posso cercare nella tabella utente molto facile. Gli svantaggi sono anche abbastanza ovvi: i dati non sono normalizzati, per qualsiasi selezione multipla (come per esempio l'hobby) ho bisogno di creare 3 colonne e se in futuro deciderò che l'utente può selezionare non 1 colore ma 2 o 3, dovrei aggiungere 2 colonne extra.
Alternativa disegno DB:
creo tavoli extra: colours
, hobbies
, marital_statuses
e creo 3 perni tabelle: user_colours
, user_hobbies
, user_marital_statuses
. Svantaggi: molti si uniscono. Vantaggi: se avessi creato 3 tabelle pivot aggiuntive, avrei potuto facilmente consentire all'utente di selezionare fino a 10 colori e non ho affatto bisogno di un database di riprogettazione. Ma si verificano anche degli svantaggi: ricerca difficile, molto lavoro, molti join.
domanda dettagliata
Quindi, per riassumere - quale soluzione sarebbe meglio assumendo:
- io probabilmente non cambiare il numero massimo di uno proprietà (se ho deciso permetto massimo 3 hobby, questo probabilmente non cambierà mai)
- Le liste di scelta per molti campi sarebbero relativamente brevi (per la maggior parte di esse meno di 10)
- Ho bisogno di cercare molto in tale database. Qualcuno, ad esempio, desidera cercare utenti che hanno impostato il colore fav_color al rosso e hanno musica per hobby.
Se ci sono altre soluzioni o vantaggi/svantaggi si vede che apprezzo condividere con me.
Ecco un'altra opzione. Creare una tabella di attributi con attributeName, attributeType, attributeValue, userId. Ciò ti consentirà di aggiungere tutti gli attributi a un utente come desideri. Evitare di dover apportare modifiche allo schema di interruzione ogni volta che si pensa a un nuovo bit di informazioni che si desidera. – paqogomez
@paqogomez: che è un anti-modello chiamato "valore-attributo entità" ma probabilmente la soluzione che fa meno male qui. Un'altra opzione sarebbe quella di memorizzare gli "attributi dinamici" come un documento JSON o XML. Ma questo rende molto difficile gestirli in SQL. Una terza opzione potrebbe essere l'aggiornamento a Postgres e l'uso delle funzionalità NoSQL di Postgres come il tipo di dati chiave/valore 'hstore' o il supporto JSON incorporato –
@a_horse_with_no_name In realtà avevo un commento che suggeriva un'opzione NoSQL, ma l'ho rimosso . Ho pensato che non era la direzione che l'OP voleva andare. È esattamente questo tipo di dati per cui NoSQL è stato creato. – paqogomez