2011-02-07 18 views
5

Sto aggiungendo una nuova funzione al mio modulo utente per il mio CMS e ho colpito un blocco stradale ... O credo, un fork in the road, e volevo ottenere alcune opinioni da StackOverflow prima di impegnarmi a nulla.
In pratica, voglio consentire agli amministratori di aggiungere nuovi campi utente "extra" che gli utenti possono compilare alla registrazione, modificare nel proprio profilo e/o essere controllati da altri moduli. Un esempio di questo sarebbe un campo di compleanno, una lunga descrizione di se stessi, o forse punti che l'utente ha guadagnato sul sito. Inutile dire che i dati memorizzati saranno variati e possono variare da grandi quantità di testo a un valore intero piccolo. Per peggiorare le cose, voglio che ci sia la possibilità di cercare questi dati.Il modo migliore per archiviare dati utente "extra" in MySQL?

Con quello fuori mano - quale sarebbe il modo migliore per farlo? In questo momento mi sto appoggiando ad avere un tavolo con le seguenti colonne.

userid, refFieldID, varchar, tinyint, smallint, int, text, date, datetime, etc. 

io preferirei questo come sarebbe rendere la ricerca molto più veloce, e la tabella di riferimento (che detiene tutti i dati del campo, come ad esempio il nome del campo, se è ricercabile o no, ecc) può fare riferimento a quale colonna deve essere usata quando si memorizzano i dati per quel campo.

L'altra idea, che mi è stata suggerita e che ho visto utilizzata in altre soluzioni (vBulletin è una, anche se ho visto altri i cui nomi mi sfuggono al momento), dove hai appena l'ID utente, l'ID di riferimento e un campo di testo. Non so abbastanza su MySQL per dirlo con certezza, ma questo metodo sembra che sia più lento per la ricerca, e possibilmente avere un sovraccarico maggiore.

Quindi quale metodo sarebbe "migliore"? C'è un altro metodo che mi manca? Qualunque sia il metodo che uso, deve essere veloce per la ricerca, non massiccia (un po 'di overhead va bene), e preferibilmente consentire query complesse usate contro i dati.

risposta

3

Sono d'accordo che una tabella valori-chiave è probabilmente la soluzione migliore. La mia prima inclinazione sarebbe quella di memorizzare una colonna di testo, come ha fatto vBulletin. Ma, se si vuole aggiungere la possibilità per l'archivio dati per essere un po 'più estensibile e ricercabili come hai disposto, Potrei suggerire:

  • 1 medio/longtext o medio/campo LONGBLOB per il testo arbitrario/binary storage (qualunque cosa sia memorizzata + overhead di 3-4 byte per la lunghezza della stringa). L'unico motivo per scegliere medio su lungo è limitare ciò che può essere memorizzato in 2^24 byte (16,7 MB) rispetto a 2^32 byte (2 GB).
  • 1 intero (4 byte) o bigint (8 byte)
  • 1 datetime (8 byte)
  • Forse 1 float o doppia (4-8 byte) per stoccaggio galleggiante punto

Questi campi ti consentirà di archiviare quasi tutti i tipi di dati nella tabella ma senza aumentare la larghezza della tabella ** (come farebbe un varchar) ed evitare qualsiasi spazio di archiviazione ridondante (come avere tinyint e mediumint ecc.). Il testo memorizzato nel campo longtext può ancora essere ricercato in modo ragionevole utilizzando un indice fulltext o un indice di lunghezza limitata normale (ad esempio index longtext_storage(8)).

** tutti i valori di blob, ad esempio il longtext, vengono memorizzati indipendentemente dalla tabella principale.

+0

Wow, grazie, in realtà stavo per rispondere alla prima persona che ha concordato con # 1, quali colonne scegliere - ma suppongo di non doverlo più :). Per quanto riguarda il tuo post, intendi testo AND blob, int AND bigint? O l'uno o l'altro? Inoltre, come ti senti ad aggiungere una colonna "bool" (tinyint (1))? Potrei vedere che è molto utile e probabilmente usato molto - varrebbe la pena di salvare i 3 byte, secondo lei? Inoltre, il numero di colonne aumenta la dimensione di una riga sul disco? Colonne vuote, ovviamente. Non sto dubitando della tua disposizione (stupenda) della tabella, solo curiosa. – Jon

+0

1 per ogni elemento nel mio elenco, quindi 3 o 4 colonne totali, a seconda se si desidera il supporto float. Come per tinyint (1) - memorizza quelli nella colonna intera. Stai sprecando un byte aggiungendo tinyint (1), non salvando 3. Ogni riga della tua tabella ha sempre la stessa larghezza in MySQL - funziona allo stesso modo nella maggior parte degli altri RDBMS. (Il modo in cui i varchar influiscono su questo diventa un po 'complicato). "Larghezza" è anche chiamato "dimensione della riga". – wuputah

0

Una tecnica che potrebbe funzionare per voi è quella di memorizzare questi dati arbitrari come testo, in alcune notazioni come JSON, XML o YAML. Questa decisione dipende dal modo in cui avrai bisogno di accedere ai dati: se cerchi solo la porzione completa di dati utente di ciascun utente, potrebbe essere l'ideale. Se è necessario eseguire query SQL su campi specifici nei dati utente, è necessario utilizzare un approccio SQL puro o ibrido.

Molti dei sistemi "NoSQL" più recenti e altamente scalabili sembrano privilegiare i dati JSON (ad esempio, MongoDB, CouchDB e Project Voldemort). È piacevole e conciso, e puoi creare strutture arbitrariamente complesse, incluse mappe (oggetti JSON) ed elenchi (matrici JSON).

Problemi correlati