2012-06-21 21 views
5

Ho visto un commento "Se si dispone di 50 milioni di valori compresi tra 10 e 15 caratteri in una colonna varchar (20) e gli stessi 50 milioni di valori in una colonna varchar (50), occuperanno esattamente lo stesso spazio. intero punto di varchar, in contrapposizione a char. ". Qualcuno può dirmi la ragione? Vedi What is a reasonable length limit on person "Name" fields?varchar (20) e varchar (50) sono uguali?

+1

Impone un * limite * logico (ad esempio una regola BO o una "sicurezza"). Si prega di cercare SO - è venuto prima e in generale finisce in un dibattito di guerra fiamme. –

+0

@rabudde: ne sei sicuro? Puoi dare un riferimento? Sarei ** molto ** sorpreso se la lunghezza definita fosse inserita nell'indice di una colonna varchar (ora 'char' è una cosa diversa). Nessun DBMS che conosca memorizza l'intera lunghezza dell'indice, ma MySQL è sempre buono per sorprese. –

+1

@pst, a_horse_with_no_name: hai ragione, ero confuso su un altro fatto (UTF8 e indici), e questo è esattamente il punto, una lunghezza 'varchar' troppo grande può comportare scarse prestazioni su ordinamento o operazioni su tabelle temporanee (referenziato in MySQL ad alte prestazioni da O'Rilly) – rabudde

risposta

5

MySQL offre una scelta di motori di archiviazione. L'archiviazione fisica dei dati dipende dal motore di archiviazione.

MyISAM bagagli di VARCHAR

In MyISAM, VARCHAR s occupa tipicamente solo la lunghezza effettiva della stringa più un byte o due di lunghezza. Ciò è reso pratico dalla limitazione del design di MyISAM al blocco del tavolo rispetto alla capacità di chiusura di una fila. Le conseguenze sulle prestazioni includono un profilo di cache più compatto, ma anche un calcolo più complicato (più lento) degli offset di record.

(In realtà, MyISAM si dà a degree of choice tra dimensione di riga fisico costante e formati tabella di misura delle righe fisiche variabili a seconda del tipo di colonna verificano nella intera tabella. Presenza di VARCHAR cambia il metodo di default solo, ma la presenza di un TEXT blob forzeVARCHAR s nella stessa tabella di utilizzare il metodo di lunghezza variabile pure.)

metodo di memorizzazione fisico è particolarmente importante con indici, che è una storia diversa rispetto alle tabelle. MyISAM utilizza la compressione spazio per entrambe le colonneCHAR e VARCHAR, il che significa che i dati più brevi occupano meno spazio nell'indice in entrambi i casi.

InnoDB bagagli di VARCHAR

InnoDB, come la maggior parte dei database relazionali, utilizza un meccanismo più sofisticato. Le colonne VARCHAR la cui larghezza massima è inferiore a 768 byte verranno archiviate in linea, con spazio riservato corrispondente alla larghezza massima. Più precisamente here:

Per ciascun campo di lunghezza variabile non NULL, l'intestazione record contiene la lunghezza della colonna in una o due byte. Due byte saranno solo necessari se parte della colonna viene archiviata esternamente nelle pagine di overflow o la lunghezza massima supera 255 byte e la lunghezza effettiva supera 127 byte. Per una colonna memorizzata esternamente, la lunghezza di due byte indica la lunghezza della parte memorizzata internamente più il puntatore da 20 byte a la parte memorizzata esternamente. La parte interna è 768 byte, quindi la lunghezza è 768 + 20. Il puntatore a 20 byte memorizza la lunghezza effettiva della colonna .

InnoDB attualmente non esegue la compressione dello spazio nei suoi indici, l'opposto di MyISAM come descritto sopra.

Torna alla domanda

Tutto quanto sopra è comunque solo un dettaglio attuativa che può anche cambiare tra le versioni. La vera differenza tra CHAR e VARCHAR è semantica, così come quella tra VARCHAR(20) e VARCHAR(50). Garantendo che non è possibile memorizzare una stringa di 30 caratteri in un VARCHAR(20), il database rende la vita più facile e meglio definita per vari processori e applicazioni che si suppone si integri in una soluzione prevedibile. Questo è il grosso problema.

Per quanto riguarda i nomi personali in particolare, this question può darti qualche consiglio pratico. Le persone con nomi completi di oltre 70 caratteri UTF-8 sono comunque nei guai.

3

Sì, è proprio questo il punto di VARCHAR. Occupa solo tanto spazio quanto il testo è lungo.

Se si disponesse di CHAR (50), occorrerebbero 50 byte (o caratteri) indipendentemente dalla lunghezza effettiva dei dati (verrà riempito, in genere da spazi).

Qualcuno può dirmi il motivo?

Perché la gente pensava che fosse inutile conservare un sacco di imbottiture inutili, hanno inventato VARCHAR.

+0

In realtà è un po 'più complicato di "inutile padding": come dire "foo" da "foo" in un CHAR (4)? –

+0

Vero. Una specie di. Questo potrebbe essere importante per alcune persone.Ho sempre un sacco di downvotes quando ne parlo (di solito nel contesto della decisione di Oracle di trattare le stringhe vuote come NULL), ma metto in discussione il design dell'applicazione che deve differenziare tra "foo" e "foo". (come puoi vedere da questo thread di commenti, anche qui le virgolette possono essere una soluzione possibile, oppure potresti usare qualcos'altro che non è altrimenti usato). – Thilo

+0

Per visualizzare un positivo su CHAR: consente record a lunghezza fissa. Può essere importante per alcune applicazioni speciali. – Thilo

2

The manual stati:

I tipi CHAR e VARCHAR sono dichiarati con una lunghezza che indica il numero massimo di caratteri che si desidera memorizzare. (...)

Contrariamente a CHAR, i valori VARCHAR vengono memorizzati come prefisso di lunghezza di un byte o di due byte più dati. Il prefisso della lunghezza indica il numero di byte nel valore. Una colonna utilizza un byte di lunghezza se i valori non richiedono più di 255 byte, due byte di lunghezza se i valori possono richiedere più di 255 byte.

noti che VARCHAR (255) è non lo stesso come VARCHAR (256).

Questa è teoria. Come suggerito da habeebperwad, l'effettivo ingombro di una riga dipende dalle dimensioni della pagina (motore) e dalla dimensione del blocco (disco rigido).