Domanda

Non ho molta esperienza nella progettazione di tabella. Il mio obiettivo è quello di creare uno o più prodotti tabelle che soddisfano i requisiti di seguito:

  • Supporto molti tipi di prodotti (TV, telefono, PC, ...). Ogni tipo di prodotto ha un diverso insieme di parametri, come:

    • Telefono avrà a colori, dimensioni, peso, sistema operativo ...

    • PC avrà CPU, HDD, RAM ...

  • Il set di parametri deve essere dinamica. È possibile aggiungere o modificare qualsiasi parametro che ti piace.

Come posso rispondere a queste esigenze, senza una tabella separata per ogni tipo di prodotto?

È stato utile?

Soluzione

Hai almeno queste cinque opzioni per modellare la gerarchia dei tipi descrivere:

  • Single Table Inheritance : una tabella per ogni tipo di prodotto, con un numero sufficiente di colonne memorizzare tutti gli attributi di tutti i tipi. Questo significa che molto di colonne, la maggior parte dei quali sono NULL su una determinata riga.

  • Classe Table Inheritance : una tabella per i prodotti, la memorizzazione di attributi comuni a tutti i prodotti tipi. Poi una tabella per ogni tipo di prodotto, memorizzare attributi specifici per il tipo di prodotto.

  • Concrete Table Inheritance : nessuna tabella per i comuni attributi. Invece, una tabella per ogni tipo di prodotto, la memorizzazione entrambi attributi di prodotto comuni, e gli attributi specifici dei prodotti.

  • LOB serializzato : Una tabella per i prodotti, l'archiviazione attributi comuni a tutti i tipi di prodotto . Una colonna memorizza in più una goccia di dati semi-strutturati, in XML, YAML, JSON, o qualche altro formato. Questo BLOB consente di memorizzare gli attributi specifici per ogni tipo di prodotto. È possibile utilizzare Design Patterns di fantasia per descrivere questo, come ad esempio Facciata e Memento. Ma a prescindere di avere un blob di attributi che non possono essere facilmente interrogati all'interno di SQL; si deve prendere tutto il blob indietro all'applicazione e ordinare là fuori.

  • Entità-attributo-valore : Una tabella per i prodotti, e una tabella che ruota attribuisce a righe, invece di colonne. EAV non è un disegno valido rispetto al paradigma relazionale, ma molte persone lo usano comunque. Questo è il "Pattern Proprietà" di cui parla un'altra risposta. Vedi altre domande con la EAV tag su StackOverflow per alcune delle insidie.

Ho scritto più su questo in una presentazione, Extensible Data Modeling .


Ulteriori pensieri su EAV: Anche se molte persone sembrano favorire EAV, non lo faccio. Sembra che la soluzione più flessibile, e quindi la migliore. Tuttavia, tenere a mente l'adagio TANSTAAFL . Ecco alcuni degli svantaggi di EAV:

  • Non c'è modo di fare una colonna obbligatoria (equivalente di NOT NULL).
  • Non c'è modo di utilizzare i tipi di dati SQL per convalidare le voci.
  • Non c'è modo di garantire che i nomi degli attributi siano scritte in modo coerente.
  • Non c'è modo di mettere una chiave esterna sui valori di un determinato attributo, per esempio per una tabella di ricerca.
  • il recupero dei risultati in un layout tabellare convenzionale è complessa e costosa, perché per ottenere gli attributi da più righe che dovete fare JOIN per ogni attributo.

Il grado di flessibilità EAV dà si richiede sacrifici in altri settori, probabilmente rendendo il codice così complesso (o peggio) di quanto non sarebbe stato quello di risolvere il problema originale in un modo più convenzionale.

E nella maggior parte dei casi, è necessario avere quel grado di flessibilità. Nella domanda del PO sui tipi di prodotti, è molto più semplice di creare una tabella per ogni tipo di prodotto per gli attributi specifici del prodotto, in modo da avere qualche struttura coerente applicata almeno per le voci dello stesso tipo di prodotto.

userei EAV solo se ogni riga deve essere permesso di avere potenzialmente una serie distinta di attributi. Quando si dispone di un insieme finito di tipi di prodotto, EAV è eccessivo. Classe Ereditarietà delle tabelle sarebbe la mia prima scelta.


Update 2019: più vedo persone che utilizzano JSON come una soluzione per il problema "molti attributi personalizzati", meno mi piace questa soluzione. Rende query troppo complessa, anche quando si utilizza speciale a loro sostegno. Ci vuole molto più spazio di archiviazione per archiviare i documenti JSON, contro la conservazione in righe e colonne normali.

In sostanza, nessuna di queste soluzioni sono facili o efficiente in un database relazionale. L'intera idea di avere "attributi variabili" è fondamentalmente in contrasto con la teoria relazionale.

Che si tratta di è che devi scegliere una delle soluzioni in base alla quale è il meno peggio per tuo app. Pertanto è necessario sapere come si sta andando a interrogare i dati prima di scegliere una progettazione di database. Non c'e 'modo di scegliere uno soluzione che è "migliore" perché una delle soluzioni potrebbe essere migliore per una data applicazione.

Altri suggerimenti

@StoneHeart

Vorrei andare qui con EAV e MVC tutta la strada.

@ Bill Karvin

  

Ecco alcuni degli svantaggi di   EAV:

No way to make a column mandatory (equivalent of NOT NULL).
No way to use SQL data types to validate entries.
No way to ensure that attribute names are spelled consistently.
No way to put a foreign key on the values of any given attribute, e.g.
     

per una tabella di ricerca.

Tutte quelle cose che hai menzionato qui:

  • la convalida dei dati
  • nomi degli attributi ortografia convalida
  • Colonne obbligatorie / campi
  • gestire la distruzione di attributi dipendenti

a mio parere non appartengono in un database a tutti perché nessuno di basi di dati sono in grado di gestire queste interazioni e le esigenze a livello adeguato, come un linguaggio di programmazione di un'applicazione fa.

A mio parere utilizzando un database in questo modo è come usare una roccia a piantare un chiodo. Si può fare con una pietra, ma non è vero supponiamo di utilizzare un martello che è più preciso e specifico per questo tipo di attività?

  

risultati Recupero di in un layout tabulare convenzionale è complesso e   costoso, perché per ottenere gli attributi   da più righe che devi fare JOIN   per ogni attributo.

Questo problema può essere risolto facendo poche query su dati parziali e loro trasformazione in layout di tabelle con la vostra applicazione. Anche se si dispone di 600 GB di dati di prodotto è possibile elaborarlo in lotti se si richiede i dati di ogni singola riga in questa tabella.

Proseguendo Se volete migliorare le prestazioni delle query è possibile selezionare alcune operazioni, come per esempio di segnalazione o di ricerca di testo globale e preparare per loro tabelle di indice che memorizzare i dati richiesti e sarebbe rigenerati periodicamente, consente di dire ogni 30 minuti.

Non c'è nemmeno bisogno di essere interessati con il costo di memorizzazione dei dati in più perché diventa più conveniente e meno costoso ogni giorno.

Se volete ancora essere interessati con le prestazioni delle operazioni effettuate con l'applicazione, si può sempre usare Erlang, C ++, Go lingua pre-elaborare i dati e più tardi solo elaborare i dati ottimizzati ulteriormente nella vostra applicazione principale.

Se uso significato Class Table Inheritance:

  

una tabella per i prodotti, la memorizzazione di attributi comuni a tutti i tipi di prodotti. Poi una tabella per ogni tipo di prodotto, memorizzazione attributi specifici per tale tipo di prodotto.   -Bill Karwin

Il che mi piace di più di suggerimenti di Bill Karwin .. Posso tipo di prevedere uno svantaggio, che cercherò di spiegare come evitare di diventare un problema.

Che piano di emergenza dovrei avere in atto quando un attributo comune solo per 1 tipo, allora diventa comune a 2, poi 3, etc?

Ad esempio: (questo è solo un esempio, non è il mio vero problema)

Se vendiamo mobili, potremmo vendere sedie, lampade, divani, televisori, ecc Il tipo di TV potrebbe essere l'unico tipo che portare che ha un consumo di energia. Quindi mi sento di mettere l'attributo power_consumption sul tv_type_table. Ma poi cominciamo a portare i sistemi home theater che hanno anche una proprietà power_consumption. OK il suo solo un altro prodotto quindi mi aggiungere questo campo al stereo_type_table così dal momento che è probabilmente più facile a questo punto. Ma nel corso del tempo, come si comincia a portare sempre più elettronica, ci rendiamo conto che power_consumption è abbastanza ampio che dovrebbe essere nel main_product_table. Cosa devo fare adesso?

Aggiungere il campo al main_product_table. Scrivere uno script per un ciclo tra l'elettronica e mettere il valore corretto da ogni type_table al main_product_table. Poi eliminare la colonna da ogni type_table.

Ora, se mi è stato sempre usando la stessa classe GetProductData per interagire con il database per tirare le informazioni del prodotto; quindi se eventuali modifiche nel codice ora hanno bisogno di refactoring, dovrebbero essere solo quella Classe.

Si può avere una tabella di prodotto e un tavolo ProductAdditionInfo separata con 3 colonne: ID prodotto, ulteriore Nome Informazioni, valore informazioni aggiuntive. Se il colore è usato da molti, ma non tutti i tipi di prodotti si potrebbe avere si tratti di una colonna Null nella tabella prodotto, o semplicemente metterlo in ProductAdditionalInfo.

Questo approccio non è una tecnica tradizionale per un database relazionale, ma ho visto ha usato molto in pratica. Può essere flessibile ed avere buone prestazioni.

Steve Yegge chiama questo il modello Proprietà e ha scritto un lungo post sul suo utilizzo.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top