Sto lavorando per aggiornare il database dei prodotti del nostro sito Web. È costruito in MySQL ma questa è più una domanda generale sul modello di progettazione del database.
Sto pensando di passare a un modello Supertipo / Sottotipo. Il nostro database attuale / precedente è principalmente una singola tabella che contiene dati su un singolo tipo di prodotto. Stiamo cercando di espandere la nostra offerta di prodotti per includere prodotti diversi.
Questo nuovo progetto di bozza è così:
Product product_[type] product_attribute_[name]
---------------- ---------------- ----------------------------
part_number (PK) part_number (FK) attributeId (PK)
UPC specific_attr1 (FK) attribute_name
price specific_attr2 (FK)
... ...
Ho una domanda relativa alle tabelle degli attributi del prodotto. L'idea qui è che un prodotto può avere un elenco di attributi dati come colore: rosso, verde, blu o materiale: plastica, legno, cromo, alluminio, ecc.
Questo elenco verrebbe archiviato in una tabella e la chiave primaria (PK) per quell'elemento dell'attributo verrà utilizzata nella tabella del prodotto specifico come chiave esterna (FK).
(Il libro Patterns of Enterprise Application Architecture di Martin Fowler lo chiama " Foreign Key Mapping ")
Ciò consente a un'interfaccia di un sito Web di estrarre l'elenco di attributi per un determinato tipo di attributo e di sputarlo in un menu di selezione a discesa o in qualche altro elemento dell'interfaccia utente. Questo elenco può essere considerato un elenco "autorizzato" di valori di attributo.
Il numero di join che si verificano quando si estrae un prodotto specifico mi sembra eccessivo. È necessario unire ogni tabella degli attributi del prodotto al prodotto in modo da poter ottenere i campi di quell'attributo. Comunemente, quel campo potrebbe semplicemente essere nient'altro che una stringa (varchar) per il suo nome.
Questo modello di progettazione finisce per creare un gran numero di tabelle e si finisce con una tabella per ogni attributo. Un'idea per contrastare questo sarebbe quella di creare qualcosa di più di una tabella "grab bag" per tutti gli attributi del prodotto. Qualcosa come questo:
product_attribute
----------------
attributeId (PK)
name
field_name
In questo modo, il tuo tavolo potrebbe apparire così:
1 red color
2 blue color
3 chrome material
4 plastic material
5 yellow color
6 x-large size
Questo potrebbe aiutare a ridurre lo scorrimento della tabella ma non riduce il numero di join e sembra un po 'sbagliato combinare così tanti tipi diversi in una singola tabella. Ma saresti in grado di ottenere abbastanza facilmente tutti gli attributi di "colore" disponibili.
Tuttavia, potrebbe esserci un attributo che ha più campi di un semplice "nome" come il valore RGB di un colore. Ciò richiederebbe che l'attributo specifico abbia eventualmente un'altra tabella o abbia un singolo campo per name: value pair (che ha i suoi svantaggi).
L'ultimo modello di progettazione che mi viene in mente è l'archiviazione del valore dell'attributo effettivo nella tabella del prodotto specifico e non esiste affatto una "tabella degli attributi". Qualcosa come questo:
Product product_[type]
---------------- ----------------
part_number (PK) part_number (FK)
UPC specific_attr1
price specific_attr2
... ...
Invece di una chiave esterna per un'altra tabella, conterrebbe il valore effettivo come:
part_number color material
----------- ----- --------
1234 red plastic
Ciò eliminerebbe i join e impedirebbe lo scorrimento della tabella (forse?). Tuttavia, ciò impedisce di avere un "elenco autorizzato" di attributi. È possibile restituire tutti i valori attualmente immessi per un determinato campo (ad esempio: colore) ma ciò elimina anche l'idea di disporre di un "elenco autorizzato" di valori per un determinato attributo.
Per avere quell'elenco, dovresti comunque creare una tabella degli attributi "grab bag" o avere più tabelle (scorrimento della tabella) per ciascun attributo.
Questo crea l'inconveniente più grande (e perché non ho mai usato questo approccio) di avere ora il nome del prodotto in più posizioni.
Se hai il valore di colore "rosso" nella "tabella degli attributi principali" e lo memorizzi anche nella tabella "product_ [tipo]", un aggiornamento alla tabella "principale" causerà un potenziale problema di integrità dei dati se l'applicazione non lo fa aggiorna anche tutti i record con il vecchio valore nella tabella "product_type".
Quindi, dopo la mia lunga spiegazione e analisi di questo scenario, la mia realizzazione è che questo non può essere uno scenario insolito e potrebbe persino esserci un nome per questo tipo di situazione.
Esistono soluzioni generalmente accettate per questa sfida progettuale? Il numero potenzialmente elevato di join è accettabile se le tabelle sono relativamente piccole? La memorizzazione del nome dell'attributo, anziché dell'attributo PK, è accettabile in alcune situazioni? C'è un'altra soluzione a cui non sto pensando?
Alcune note su questo database / applicazione di questo prodotto:
- I prodotti non vengono aggiornati / aggiunti / rimossi frequentemente
- Gli attributi non vengono aggiornati / aggiunti / rimossi frequentemente
- La tabella viene più frequentemente richiesta per leggere / restituire informazioni
- La memorizzazione nella cache lato server è abilitata per memorizzare nella cache il risultato di una determinata query / risultato
- Ho intenzione di iniziare con un solo tipo di prodotto e di estenderne / aggiungerne altri nel tempo e conterrà potenzialmente più di 10 tipi diversi