MySQL VARCHAR Lengths e UTF-8


84

In MySQL, se creo un nuovo VARCHAR(32)campo in una tabella UTF-8 significa che posso memorizzare 32 byte di dati in quel campo o 32 caratteri (multibyte)?


@naXa: non l'ho fatto. Pensi che dovrei?
Alix Axel

Non lo so.) È la tua domanda e dipende da te. Volevo solo dire "un'altra risposta sembra più completa".
naXa

@robsch La precedente risposta accettata era semplice e corretta. Ma fai a grande richiesta ho accettato quello che vuoi.
Alix Axel

Risposte:


168

Questa risposta è stata visualizzata nella parte superiore dei risultati di ricerca di Google ma non era corretta, quindi:

La confusione è probabilmente dovuta alle diverse versioni di mysql in fase di test.

  • La versione 4 conta i byte
  • La versione 5 conta i caratteri

http://dev.mysql.com/doc/refman/5.0/en/string-type-overview.html

MySQL interpreta le specifiche di lunghezza nelle definizioni delle colonne di caratteri in unità di caratteri. (Prima di MySQL 4.1, le lunghezze delle colonne venivano interpretate in byte.) Questo vale per i tipi CHAR, VARCHAR e TEXT.

È interessante notare che (non ci avevo pensato) la lunghezza massima di una colonna varchar è influenzata da utf8 come segue:

La lunghezza massima effettiva di un VARCHAR in MySQL 5.0.3 e versioni successive è soggetta alla dimensione massima delle righe (65.535 byte, condivisa tra tutte le colonne) e al set di caratteri utilizzato. Ad esempio, i caratteri utf8 possono richiedere fino a tre byte per carattere, quindi una colonna VARCHAR che utilizza il set di caratteri utf8 può essere dichiarata con un massimo di 21.844 caratteri.


48
M Brown, grazie per averlo detto. Un campo VARCHAR (10) (utilizzando utf8mb4) può memorizzare "💩💩💩💩💩💩💩💩💩💩" (10 pile di cacca), ovvero 10 caratteri ma 40 byte.
basic6

3
Questo. Questa è l'unica risposta giusta. Troppe persone credono che il comportamento della versione 4 sia vangelo.
Brendan Byrd

2
La risposta accettata è corretta anche per MySQL 5 - i numeri inseriti facevano effettivamente parte del set di caratteri a larghezza intera e sono caratteri unicode multibyte, come menzionato anche dal poster che ha inserito "32 multibytes data". È un peccato che così tante persone abbiano capito male.
user193130

Citando la seguente fonte, credo che un carattere utf8 attualmente richieda fino a 6 byte, quindi ovunque tra 1 e 6 byte. Questo fa sì che il caso peggiore per un massimo di caratteri sia 10922. Penso. joelonsoftware.com/articles/Unicode.html
usumoio

1
@usumoio Attualmente, sembra che MySQL utilizzi la variante a 3 byte di UTF-8, con la migrazione alla variante (standard) a 4 byte pianificata: dev.mysql.com/doc/refman/8.0/en/charset-unicode -utf8.html .
flow2k

8

ti consentirebbe di memorizzare 32 caratteri multibyte

Per risparmiare spazio con UTF-8, usa VARCHAR invece di CHAR. Altrimenti, MySQL deve riservare tre byte per ogni carattere in una colonna CHARACTER SET utf8 perché questa è la lunghezza massima possibile. Ad esempio, MySQL deve riservare 30 byte per una colonna CHAR (10) CHARACTER SET utf8.

http://dev.mysql.com/doc/refman/5.0/en/charset-unicode.html


Non lo uso quasi mai CHARe quando lo faccio non è destinato a memorizzare caratteri multibyte, quindi sono al sicuro. Che dire VARCHAR, sei sicuro che il limite sia definito in caratteri multibyte e non in caratteri a byte singolo?
Alix Axel

9
@jspcal: UTF-8 utilizza un massimo di 4 byte per carattere, non 3. O MySQL non supporta tutti e 4 i byte?
Remy Lebeau

5
@ RemyLebeau Hai ragione su utf8, ma non su MySQL. I vari set di caratteri utf8_xxx hanno un massimo di 3 byte. L'utf8mb4_xxx accetta caratteri da 4 byte. dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Buttle Butkus

Con il progredire del tempo, sembra che MySQL finalmente utilizzerà la versione standard a 4 byte (ma non ancora, al momento della scrittura): dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8 .html .
flow2k

6

32 multibyte di dati per le varchar(32)regole di confronto utf8_unicode_ci, ho appena testato con XAMPP.

1234567890123456789012345678901234567890

Ottieni troncato a:

12345678901234567890123456789012

Tieni presente che questi non sono caratteri ASCII regolari.


4
Nello standard UTF-8 i caratteri ASCII verranno memorizzati solo in un singolo byte - per verificarlo veramente è necessario utilizzare effettivamente alcuni caratteri multibyte (cioè non ascii) nel test sting.
rjmackay

5
Questo è sbagliato, almeno per MySQL 5+. Quando si specifica la dimensione della colonna per varchar o char, viene specificata in termini di caratteri. Credo che la dimensione effettiva di una colonna VARCHAR (32) sarebbe 32x3 + 1 = 97 byte.
Buttle Butkus

5
@rjmackay '12345' non sono caratteri ASCII standard. en.wikipedia.org/wiki/…
Alexey Lebedev

7
Ho inserito 40 caratteri Unicode nel DB e sono stato troncato a 32 caratteri. Ma sembra che la gente pensi che abbia usato byte ascii e che venga troncato a 32 byte. Non c'è da stupirsi, ho ricevuto voti negativi, lol.
YOU

2
@ButtleButkus "Credo che la dimensione effettiva di una colonna VARCHAR (32) sarebbe 32x3 + 1 = 97 byte" Lo sarebbe se lo usassi utf8, ma poi ottieni un supporto Unicode non funzionante in MySQL. Dovresti utf8mb4invece usare la codifica, perché ci sono max. 4 byte in un carattere utf-8 , non 3 come nella variante MySQL di utf8 ...
Stijn de Witt

1

È preferibile utilizzare "char" per tabelle di aggiornamento molto frequenti perché la lunghezza totale dei dati della riga sarà fissa e veloce. Le colonne Varchar rendono dinamiche le dimensioni dei dati delle righe. Non va bene per MyISAM, ma non conosco InnoDB e altri. Ad esempio, se hai una colonna "tipo" molto stretta, potrebbe essere meglio usare char (2) con latin1 charset per richiedere solo uno spazio minimo.


1
Ho letto che se QUALSIASI colonna in una tabella è varchar, perdi tutti i vantaggi di avere colonne char. Fondamentalmente, sembra che devi andare con tutti i varchar o tutti i caratteri in una tabella per il massimo beneficio. Non so se sia vero, però.
Buttle Butkus

Per MyISAM c'è qualche argomento a favore CHAR. Per InnoDB, stanno accadendo così tante altre cose che il dibattito sulla "dimensione dinamica / fissa delle righe" è essenzialmente irrilevante.
Rick James

IMHO il punto importante qui è che per lunghezze molto piccole , può essere utile usarlo CHAR.
ToolmakerSteve

0

Se ti connetti al database utilizzando la codifica latin1 (ad esempio con PHP) per salvare una stringa PHP UTF8 in una colonna MySQL UTF8, avrai una doppia codifica UTF8.

Se la stringa UTF8 $sè lunga 32 caratteri ma 64 byte e la colonna è VARCHAR(32)UTF8, la doppia codifica convertirà la stringa $sin una stringa UTF8 lunga 64 caratteri che verrà troncata nel database ai suoi 32 primi caratteri corrispondenti ai primi 32 byte di $s. Potresti finire per pensare che MySQL 5 si comporti come MySQL 4 ma in realtà è una seconda causa per lo stesso effetto.

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.