MySQL: più tabelle o una tabella con molte colonne?


125

Quindi questa è più una questione di design.

Ho una chiave primaria (ad esempio l'ID dell'utente) e ho tonnellate di informazioni associate a quell'utente.

Devo avere più tabelle suddivise in categorie in base alle informazioni o dovrei avere solo una tabella con molte colonne?

Il modo in cui lo facevo era avere più tabelle, quindi diciamo, una tabella per i dati sull'utilizzo dell'applicazione, una tabella per le informazioni sul profilo, una tabella per i token back-end ecc. Per mantenere le cose organizzate.

Recentemente qualcuno mi ha detto che è meglio non farlo in quel modo e avere una tabella con tante colonne va bene. Il fatto è che tutte quelle colonne hanno la stessa chiave primaria.

Sono abbastanza nuovo nella progettazione di database, quindi quale approccio è migliore e quali sono i pro ei contro?

Qual è il modo convenzionale di farlo?


Per chiarezza, correggimi se sbaglio, ma penso che le "tabelle multiple" possano essere intese come link / tabella associativa: en.wikipedia.org/wiki/Associative_entity
cellepo

1
Questo database è necessario per scopi analitici o per l'elaborazione operativa / transazionale?
Alexander Radev

Risposte:


112

Ogni volta che le informazioni sono uno a uno (ogni utente ha un nome e una password), allora è probabilmente meglio avere una tabella, poiché riduce il numero di join che il database dovrà fare per recuperare i risultati. Penso che alcuni database abbiano un limite al numero di colonne per tabella, ma non me ne preoccuperei nei casi normali e puoi sempre dividerlo in un secondo momento, se necessario.

Se i dati sono uno-a-molti (ogni utente ha migliaia di righe di informazioni sull'utilizzo), allora dovrebbero essere suddivisi in tabelle separate per ridurre i dati duplicati (i dati duplicati sprecano spazio di archiviazione, spazio nella cache e rendono il database più difficile da mantenere ).

Potresti trovare interessante l'articolo di Wikipedia sulla normalizzazione del database , poiché discute le ragioni in modo approfondito:

La normalizzazione del database è il processo di organizzazione dei campi e delle tabelle di un database relazionale per ridurre al minimo la ridondanza e la dipendenza. La normalizzazione di solito comporta la divisione di tabelle di grandi dimensioni in tabelle più piccole (e meno ridondanti) e la definizione delle relazioni tra di esse. L'obiettivo è isolare i dati in modo che le aggiunte, le eliminazioni e le modifiche di un campo possano essere apportate in una sola tabella e quindi propagate nel resto del database tramite le relazioni definite.

Anche la denormalizzazione è qualcosa di cui essere consapevoli, perché ci sono casi in cui è meglio ripetere i dati (poiché riduce la quantità di lavoro che il database deve fare durante la lettura dei dati). Consiglio vivamente di rendere i tuoi dati il ​​più normalizzati possibile per iniziare e denormalizzarli solo se sei a conoscenza di problemi di prestazioni in query specifiche.


Grazie per la tua risposta, quindi dopo averlo letto penso che quello di cui stavo parlando fosse la situazione delle informazioni one-to-one, quando un utente ha molte colonne one-to-one.
Xavier_Ex

@Xavier_Ex - Sì, se c'è solo una colonna per utente, sarà più facile lavorare con una sola enorme tabella utenti (e molto più facile da ottimizzare per il motore DB).
Brendan Long

Il tuo post modificato fornisce informazioni più utili! Ho una nuova preoccupazione che se alcune delle colonne verranno aggiornate frequentemente, dovrei inserirle in tabelle separate? Ad esempio la data di nascita di un utente non verrà mai aggiornata, ma il token di back-end potrebbe essere invalidato dopo un periodo di tempo e richiederà aggiornamenti frequenti. Sarebbe meglio se separassi le tabelle in questo modo per migliorare le prestazioni? Ora vado a leggere del wiki che hai menzionato :)
Xavier_Ex

@Xavier_Ex - Non lo consiglierei. Si ottengono prestazioni notevolmente migliori quando è possibile cercare tutti i dati necessari in una tabella (vedere l'articolo sulla denormalizzazione). I join sono costosi perché (1) richiedono la ricerca di dati in più posizioni, il che può comportare ricerche su un disco rotante, (2) generalmente richiedono più indici e una sorta di unione e (3) rendono più difficile la pianificazione delle query, il che non richiede solo tempo, ma aumenta anche le possibilità che l'ottimizzatore di query ottenga qualcosa di sbagliato (e le query mal ottimizzate possono essere molto lente).
Brendan Long

1
Recentemente ho dovuto affrontare lo stesso problema, perché le tabelle MySQL InnoDB hanno un limite di lunghezza relativamente piccolo (~ 8000 byte). Nella mia tabella dei problemi (dati da moduli assicurativi molto lunghi, più di 100 colonne) abbiamo più colonne varchar, tutte UTF8. Quindi abbiamo facilmente riempito il limite di ~ 8000 byte e ottenuto "errore 139 dallo storage engine" tutto il tempo. Quindi abbiamo dovuto dividere il tavolo. (Abbiamo testato con il formato Barracuda più recente e ha funzionato senza divisioni, ma i server dei nostri clienti usano ancora MySQL 5.0).
MV.

12

Un grande tavolo è spesso una scelta sbagliata. Le tabelle correlate sono ciò con cui il database relazionale è stato progettato per funzionare. Se indicizzi correttamente e sai come scrivere query performanti, funzioneranno bene.

Quando le tabelle ottengono troppe colonne, è possibile riscontrare problemi con le dimensioni effettive della pagina su cui il database memorizza le informazioni. O il record può finire per essere troppo grande per la pagina, in cui potresti finire per non essere in grado di creare o aggiornare un record specifico che rende gli utenti infelici o potresti (almeno in SQL Server) essere consentito un overflow per particolari datatypes (con una serie di regole che devi cercare se lo stai facendo) ma se molti record superano le dimensioni della pagina puoi creare enormi problemi di prestazioni. Ora come MYSQL gestisce le pagine e se hai un problema quando la potenziale dimensione della pagina diventa troppo grande è qualcosa che dovresti cercare nella documentazione di quel database.


1
Ah voci diverse! Che è sempre fantastico. Grazie per le vostre informazioni! Mi assicurerò di esserne consapevole quando creo i miei tavoli ... ma non sapevo che avrei dovuto essere a conoscenza di cose di così basso livello originariamente.
Xavier_Ex

4

Ho un buon esempio. Database eccessivamente normalizzato con il seguente insieme di relazioni:

people -> rel_p2staff -> staff

e

people -> rel_p2prosp -> prospects

Dove le persone hanno nomi e dettagli delle persone, il personale ha solo i dettagli del record del personale, i potenziali clienti hanno solo i dettagli dei potenziali clienti e le tabelle rel sono tabelle delle relazioni con chiavi esterne di persone che si collegano a personale e potenziali clienti.

Questo tipo di progettazione continua per l'intero database.

Ora per interrogare questo insieme di relazioni è un join multi-tabella ogni volta, a volte 8 e più join di tabella. Ha funzionato bene fino alla metà di quest'anno, quando ha iniziato a rallentare ora che abbiamo superato i 40000 record di persone.

L'indicizzazione e tutti i frutti a bassa pendenza sono stati esauriti l'anno scorso, tutte le query sono ottimizzate alla perfezione. Questa è la fine della strada per la particolare progettazione normalizzata e la gestione ora ha approvato una ricostruzione dell'intera applicazione che dipende da essa così come la ristrutturazione del database, in un periodo di 6 mesi. $$$$ Ahi.

La soluzione sarà avere una relazione diretta per people -> staffepeople -> prospect


Sarebbe interessato a sapere come è andata la ricostruzione? Hai finito per progettare qualcosa di simile all'ereditarietà di una singola tabella in cui avevi un typeessere a staffo a prospect?
Coderama

1
Sono andato con relazioni dirette persone -> personale e persone -> potenziale cliente, funziona in modo affascinante, facile da usare, veloce da interrogare.
Vlad

4

Mi sono imbattuto in questo, e come qualcuno che usava molto MySQL e poi è passato a Postgres di recente, uno dei grandi vantaggi è che puoi aggiungere oggetti JSON a un campo in Postgres.

Quindi, se ti trovi in ​​questa situazione, non devi necessariamente decidere tra una grande tabella con molte colonne e suddividerla, ma puoi unire le colonne in oggetti JSON per ridurla, ad esempio invece di essere l'indirizzo di 5 colonne, può semplicemente Sii uno. Puoi anche eseguire query su quell'oggetto.


che dire delle prestazioni quando si utilizza l'oggetto json durante la query?
dagalti

1
@dagalti la performance va bene per le applicazioni su cui l'ho usata. Non ho fatto il mio benchmark su di esso, ma questo potrebbe esserti utile: arangodb.com/2018/02/…
moinhaque

3

poniti queste domande se metti tutto in una tabella, avrai più righe per quell'utente? Se devi aggiornare un utente, vuoi mantenere un audit trail? L'utente può avere più di un'istanza di un elemento dati? (come il numero di telefono per esempio) avrai un caso in cui potresti voler aggiungere un elemento o un insieme di elementi in un secondo momento? se rispondi sì, molto probabilmente vorrai avere tabelle figlie con relazioni di chiave esterna.

I vantaggi delle tabelle padre / figlio sono l'integrità dei dati, le prestazioni tramite indici (sì, puoi farlo anche su una tabella piatta) e IMO più facile da mantenere se devi aggiungere un campo in un secondo momento, specialmente se sarà un campo obbligatorio.

Il design dei contro è più difficile, le query diventano leggermente più complesse

Ma ci sono molti casi in cui un grande tavolo piatto sarà appropriato, quindi devi guardare la tua situazione per decidere.


Grazie per avermelo ricordato! Quindi nel mio caso stavo solo considerando il caso in cui ogni utente non può avere più di una riga, quindi tutti i campi di informazioni sono uno a uno. Inoltre l'utente non può avere più di un'istanza dello stesso elemento poiché credo nel concetto di un elemento non possa esistere in più di un posto. Per la terza domanda, sì, potrei aggiungere più elementi alla tabella ma non infrangeranno i requisiti che ho menzionato sopra. Penso che la tabella genitore / figlio sia valida quando voglio associare più righe a un utente, ma in questo caso la mia preoccupazione è che un utente abbia molte colonne uno a uno.
Xavier_Ex

anche se tutti gli elementi sono attualmente uno a uno, ciò non elimina la necessità o il desiderio di avere tabelle padre / figlio IMO. Tenere un registro dei dati modificati è un uso. il caricamento pigro degli oggetti è un altro. mentre ci sono vantaggi per una singola struttura di tabella, ci sono anche vantaggi per i layout genitore figlio (anche se ho visto persone andare agli estremi anche con questi).
Brian

1

Ho già finito di progettare una sorta di database. per me dipende dalla difficoltà del sistema con la gestione del database; sì, è vero avere dati univoci in un solo posto, ma è davvero difficile fare query con database eccessivamente normalizzati con molti record. Basta combinare i due schemi; usa una tabella enorme se ritieni di avere record enormi che sono difficili da mantenere proprio come Facebook, Gmail, ecc. e usa una tabella diversa per un set di record per un sistema semplice ... beh, questa è solo la mia opinione .. spero che possa aiutare .. fallo e basta .. puoi farlo ... :)


1
"usa una tabella enorme se avrai un record enorme .." Ma Facebook, Google non memorizza i dati degli utenti in una singola tabella, li separa come molte tabelle.
Yami Odymel

0

Il modo convenzionale per farlo sarebbe utilizzare tabelle diverse come in uno schema a stella o in uno schema a fiocco di neve. Comunque, baserei questa strategia per essere duplice. Credo nella teoria secondo cui i dati dovrebbero esistere solo in un posto, lì per lo schema che ho citato funzionerebbe bene. Tuttavia, credo anche che per i motori di reporting e le suite di BI, un approccio a colonne sarebbe estremamente vantaggioso perché supporta maggiormente le esigenze di reporting. Gli approcci a colonne come quelli con infobright.org hanno enormi guadagni in termini di prestazioni e compressione che rendono l'utilizzo di entrambi gli approcci incredibilmente utile. Molte aziende stanno iniziando a rendersi conto che avere una sola architettura di database nell'organizzazione non supporta l'intera gamma delle loro esigenze. Molte aziende stanno implementando sia il concetto di avere più di un'architettura di database.


Grazie per l'informazione, ma scusa non ho capito bene la tua risposta ... farò una ricerca sui due schemi che hai menzionato per primi ...
Xavier_Ex

-4

Penso che avere una singola tabella sia più efficace ma dovresti assicurarti che la tabella sia organizzata in modo da mostrare la relazione, la tendenza e la differenza nelle variabili della stessa riga. ad esempio, se la tabella mostra l'età e i voti degli studenti, è necessario impostare la tabella in modo che, grazie al punteggio più alto, sia ben differenziata con il punteggio più basso e la differenza di età degli studenti sia pari.

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.