È buono memorizzare valori separati da virgole in una singola colonna?

2

So che questa domanda è stata probabilmente posta diverse volte prima, ma la mia domanda è specifica per la mia situazione.

Sto implementando un servizio di notifica micro. Ha una tabella email e una tabella queue . Il servizio è esposto utilizzando un'API REST. Ogni email può avere più to indirizzi e cc indirizzi. La coda ha un ID e-mail. Una volta inviata l'email, la riga viene rimossa dalla coda.

Al momento, è necessario no richiedere chi ha inviato le email o se è stata inviata un'email per un determinato utente con un determinato indirizzo email. Esistono diverse idee su come memorizzare gli indirizzi email / cc.

  1. memorizzali in formato JSON in un campo indirizzo della tabella email:
    {
         toList: ['h@h','g@g'],
         ccList: ['a@b','c@d']
    }

Ho preso in considerazione l'utilizzo del tipo di dati JSON di MySQL 5.7, ma non è supportato in h2db che usiamo per i test di integrazione.

  1. memorizzali come valori separati da virgola in toList , ccList colonne nella tabella email .

  2. Memorizzali in una tabella relazionale come email , emailaddress , emailaddresstype dove la tabella emailaddress conterrà emailid , indirizzo email e emailaddressstypeid . Ciò comporta diversi record nella tabella emailaddress e anche più join.

Quale sarebbe la migliore soluzione da implementare in questo caso? Generalmente sono contrario alla violazione dell'FNF e non sono sicuro di cosa significhi avere così tanti record in una tabella emailaddress come un record per ogni email inviata, ad esempio, a 2 o 3 persone. Non c'è una tabella user in questo sistema, se questo è importante.

    
posta TechCrunch 22.03.2017 - 20:14
fonte

4 risposte

9

Suppongo che dipenda davvero da cosa pensi di fare con i dati. Se gli indirizzi email non sono altro che elenchi di stringhe che recupererai e manipolerai da qualche altra parte, allora le stringhe separate da virgola in colonne separate ("to", "cc", "bcc") probabilmente vanno bene.

Se pensi che potresti voler interrogare ad un certo punto e chiedere "chi è stato inserito in CC su E-mail # 1234 ma NON ha fatto CC sul messaggio di risposta (# 5678)?" potrebbe essere difficile farlo con semplici elenchi separati da virgola. In tal caso, dovresti utilizzare tabelle separate per archiviare correttamente gli indirizzi email.

    
risposta data 22.03.2017 - 20:27
fonte
6

Is it good to store comma-separated values in single column

In generale, No.

L'accesso a valori di dati delimitati incorporati all'interno di un campo più ampio generalmente genera prestazioni dell'applicazione molto basse. Risultati quasi sempre in "Scansioni tabella" perché gli indici non possono essere utilizzati in modo significativo.

At this time, there is no requirement to query on who sent what emails or whether a email for a particular user with given email address is sent.

Beato te.

Attendi fino a quando non inizi una disputa con un utente che insiste che non riceve le e-mail che tu [pretendi di] averle inviate, a quel punto ti hai per avviare le query esso. OK, se queste query di scansione delle tabelle non sono la fine del mondo se devi solo eseguirne alcune ma non appena un simile genere di cose diventa luogo comune, devi passare a una struttura dati più ragionevole .

OK, la preparazione per questo tipo di utilizzo vola di fronte al mantra dello "YAGNI" degli sviluppatori ma, troppo spesso, gli amministratori di database si trovano che hanno a fare una visione a lungo termine e ad assicurarsi le strutture dati che implementano sono il più flessibili possibile; sensibilizzazione La normalizzazione è un grande passo in quella direzione.

    
risposta data 23.03.2017 - 14:07
fonte
4

Dovresti memorizzare i dati in forma normalizzata (opzione 3) a meno che tu non abbia un motivo valido per non farlo. I dati non normalizzati come nelle opzioni 1 e 2 presentano una serie di inconvenienti: rischio di incongruenze, difficoltà di analisi e interrogazione e così via.

Stai rendendo il sistema più complesso e fragile, quindi hai bisogno di una buona ragione per farlo. Alcune ragioni legittime potrebbero essere la memorizzazione nella cache di strutture di dati complesse per motivi di prestazioni o l'archiviazione di dati arbitrari che è opaco all'applicazione.

Ma non menzioni alcun motivo particolare che giustifichi dati non normalizzati, quindi vai con 3.

(Si suggerisce un inconveniente dell'opzione 3 è più tabelle e più join. Ma questa è una falsa pista, dato che hai la stessa quantità di dati e struttura sottostante con le altre opzioni, è solo memorizzata in un modo meno conveniente e modo ottimizzato.)

    
risposta data 23.03.2017 - 10:27
fonte
2

Il primo antipattern di cui parla Bill Karwin nel suo libro "Antipatterns SQL" è Jaywalking (perché si evita un'intersezione). L'antipattern elenca in modo specifico i problemi associati alla memorizzazione di valori separati da virgola quando è necessario utilizzarli separatamente (ad esempio, l'interrogazione della tabella diventa complicata). La soluzione offerta nel capitolo del libro è semplice: crea una tabella di intersezioni.

    
risposta data 23.03.2017 - 10:23
fonte

Leggi altre domande sui tag