2010-08-04 12 views
9

Ho una colonna in una tabella che memorizzerà un valore enum. Per esempio. Grande, Medio, Piccolo o i giorni della settimana. Questo corrisponderà al testo visualizzato su una pagina Web o alla selezione dell'utente da una lista a discesa. Qual è il miglior design?buon design del database: valori enum: ints o stringhe?

Memorizzare i valori come int e quindi forse avere una tabella che contiene la stringa enum/int corrispondente.

Basta memorizzare i valori nella colonna come una stringa, per rendere le query un po 'più auto-esplicative.

A che punto/quantità di valori è meglio utilizzare ints o stringhe.

Grazie.

+0

Un vantaggio dell'uso di stringhe è che sono più facili da leggere se tu o qualcun altro dovessi mai lavorare direttamente con il DB. Ti farà risparmiare la fatica di unirti alle tabelle che definiscono gli int per rendere le query leggibili. Ho visto implementazioni piuttosto grandi usando stringhe - l'impatto sulle prestazioni è trascurabile. –

risposta

0

Proseguendo con il primo esempio. Diciamo che crei una tabella di ricerca: dimensioni. Ha le seguenti colonne: Id - chiave primaria + identità Nome - varchar/nvarchar

Avresti tre righe della tabella, Small, Medium e Large con i valori 1, 2, 3 se li è stato inserito in quell'ordine

Se si dispone di un'altra tabella che utilizza tali valori, è possibile utilizzare il valore dell'identità come chiave esterna ... oppure è possibile creare una terza colonna, che è un valore di mano corta per i tre valori. Avrebbe i valori S, M & L. Potresti usarlo come chiave esterna. Dovresti creare un vincolo univoco sulla colonna.

Per quanto riguarda il menu a discesa, è possibile utilizzare uno dei due come valore dietro le quinte.

È anche possibile creare il valore S/M/L come chiave primaria.

Per la tua altra domanda su quando è meglio usare gli interi vs stringhe. Probabilmente c'è un sacco di dibattito sull'argomento. A molte persone piace solo usare i valori di identità come chiavi primarie. Altre persone dicono che è meglio usare una chiave naturale. Se non si utilizza un'identità come chiave primaria, è importante assicurarsi di avere un buon candidato per la chiave primaria (accertandosi che sia sempre univoca e che il valore non cambi).

2

Assumendo che il RDBMS di scelta non ha un tipo enum (che gestisce questo per voi), penso che meglio usare gli ID invece di stringhe direttamente quando i valori possono cambiare (sia in termini di valore e in quantità.)

Si potrebbe pensare che i giorni della settimana non cambieranno, ma cosa succederebbe se la propria applicazione dovesse aggiungere il supporto per l'internazionalizzazione? (o una multinazionale malvagia decide di rinominarli dopo aver preso il controllo del mondo?)

Inoltre, la classificazione di Grandi, Mezzi e Piccoli probabilmente sta cambiando dopo un po '. La maggior parte dei valori che pensi non possono cambiare, può cambiare dopo un po '.

Quindi, principalmente per anticipare i motivi del cambiamento, penso che sia meglio usare gli id, basta cambiare la tabella di traduzione e tutto funziona senza problemi. Per i18n, puoi semplicemente espandere la tabella di traduzione e tirare automaticamente i record appropriati.

Molto probabilmente (dipenderà da vari fattori) i risultati saranno migliori, almeno nella quantità di memoria richiesta. Ma non lo farei per motivi di prestazioni, lo farei per motivi di flessibilità.

+0

Non capita prima, quali RDBMS hanno il supporto ENUM? Qualcosa che ho perso per il preciso –

+0

MySQL ce l'ha: http://dev.mysql.com/doc/refman/5.0/en/enum.html –

+0

Fantastico, sto appena iniziando a dare un'occhiata a mySQL così io ' terrò d'occhio per questo. –

1

questa è una domanda interessante.Sicuramente devi prendere in considerazione gli obiettivi di performance qui. Se non vuoi andare veloce, int è un must. Un database può indicizzare gli interi un po 'meglio delle stringhe, anche se devo dire che non è affatto una cattiva perdita di prestazioni.

In questo esempio si trova il database Oracle in cui hanno il lusso di fare enum large cap come stringhe sulle proprie tabelle di sistema. Cose come USER_ALLOCATION_TYPE o cose del genere sono la norma. Come dici tu, le stringhe possono essere più "estensibili" e più leggibili, ma in ogni caso nel codice ti ritroverai con:

Stringa finale statica USER_ALLOCATION_TYPE = "USER_ALLOCATION_TYPE";

in luogo di

statico int USER_ALLOCATION_TYPE finale = 5;

Perché se lo fai, ti ritroverai con tutti questi stringhe letterali che sono solo dolorosi per qualcuno che va lì e mette un po 'in ordine! :)

Nella mia azienda utilizziamo tabelle con chiavi primarie intere; tutti i tavoli hanno una chiave primaria seriale, perché anche se non pensi di averne bisogno, prima o poi te ne pentirai.

Nel caso in cui si sta descrivendo ciò che facciamo è che abbiamo una tabella con (PK Int, Descrizione String) e quindi facciamo Visualizzazioni sulle tabelle principali con join per ottenere le descrizioni, in questo modo si arriva a vedere il descrizioni dei campi uniti, se necessario, e manteniamo le prestazioni migliori.

Inoltre, con una tabella di descrizione separata puoi avere informazioni EXTRA su quegli ID che non avresti mai pensato. Ad esempio, diciamo che un utente può avere accesso ad alcuni campi nella casella combinata se e solo se hanno tale proprietà e così via. È possibile utilizzare campi aggiuntivi nella tabella di descrizione per memorizzarli al posto del codice ad hoc.

I miei due centesimi.

0

Anch'io sarei interessato al pensiero della gente riguardo a questo, ho sempre seguito il percorso di memorizzazione dell'enumerazione in una tabella di ricerca e quindi in tutte le tabelle di dati che facevano riferimento all'enumerazione avrei archiviato l'ID e utilizzando la relazione FK . In un certo modo, mi piace ancora questo approccio, ma c'è qualcosa di semplice e semplice nel mettere il valore della stringa direttamente nella tabella.

Passando esclusivamente alla dimensione, un int è 4 byte, dove la stringa è n btyes (dove n è il numero di caratteri). Il valore più basso nella tua ricerca è di 5 caratteri, il più lungo è 6, quindi la memorizzazione del valore effettivo richiederebbe più spazio alla fine (se questo era un problema).

A causa delle prestazioni, non sono sicuro che un indice su un int o su un varchar restituirà alcuna differenza di velocità/ottimizzazione/dimensione dell'indice?

+0

Chiaro, semplice e doloroso: fare aggiornamenti se i valori cambiano ei tuoi dati crescono a un ammontare rispettabile sarà un dolore. Mantenere la coerenza tra questi cambiamenti potrebbe anche diventare un dolore. Estendere l'enum per aggiungere un nuovo valore (se lo si applica) potrebbe diventare un dolore.E probabilmente ci sono cose più dolorose a cui non sto nemmeno pensando. –