Longitudes de MySQL VARCHAR y UTF-8

84

En MySQL, si creo un nuevo VARCHAR(32)campo en una tabla UTF-8, ¿significa que puedo almacenar 32 bytes de datos en ese campo o 32 caracteres (multibyte)?

Alix Axel
fuente
@naXa: No lo hice. ¿Crees que debería?
Alix Axel
No lo sé.) Es su pregunta y depende de usted. Solo quería decir "otra respuesta parece más completa".
naXa
@robsch La respuesta aceptada anteriormente era simple y correcta. Pero obedece a la demanda popular, he aceptado el que quieres.
Alix Axel

Respuestas:

168

Esta respuesta apareció en la parte superior de los resultados de búsqueda de Google, pero no fue correcta, por lo que:

La confusión probablemente se deba a que se están probando diferentes versiones de mysql.

  • La versión 4 cuenta bytes
  • La versión 5 cuenta caracteres

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

MySQL interpreta las especificaciones de longitud en las definiciones de columnas de caracteres en unidades de caracteres. (Antes de MySQL 4.1, las longitudes de las columnas se interpretaban en bytes). Esto se aplica a los tipos CHAR, VARCHAR y TEXT.

Curiosamente (no lo había pensado) la longitud máxima de una columna varchar se ve afectada por utf8 de la siguiente manera:

La longitud máxima efectiva de un VARCHAR en MySQL 5.0.3 y posteriores está sujeta al tamaño máximo de fila (65 535 bytes, que se comparte entre todas las columnas) y al juego de caracteres utilizado. Por ejemplo, los caracteres utf8 pueden requerir hasta tres bytes por carácter, por lo que una columna VARCHAR que usa el juego de caracteres utf8 se puede declarar con un máximo de 21,844 caracteres.

M marrón
fuente
48
M Brown, gracias por mencionar esto. Un campo VARCHAR (10) (usando utf8mb4) puede almacenar "💩💩💩💩💩💩💩💩💩💩" (10 pilas de caca), eso es 10 caracteres pero 40 bytes.
básico6
3
Esta. Ésta es la única respuesta correcta. Demasiadas personas creen que el comportamiento de la versión 4 es un evangelio.
Brendan Byrd
2
La respuesta aceptada también es correcta para MySQL 5: los números insertados eran en realidad parte del conjunto de caracteres de ancho completo y son caracteres Unicode de varios bytes, como también menciona el póster de que insertó "32 datos multibytes". Es una pena que tanta gente haya entendido mal.
user193130
Citando la siguiente fuente, creo que un carácter utf8 actualmente requiere hasta 6 bytes, por lo que entre 1 y 6 bytes. Esto hace que el peor de los casos para un máximo de caracteres sea 10922. Creo. joelonsoftware.com/articles/Unicode.html
usumoio
1
@usumoio Actualmente, parece que MySQL usa la variante de 3 bytes de UTF-8, y se planea la migración a la variante (estándar) de 4 bytes: dev.mysql.com/doc/refman/8.0/en/charset-unicode -utf8.html .
flow2k
8

le permitiría almacenar 32 caracteres multibyte

Para ahorrar espacio con UTF-8, use VARCHAR en lugar de CHAR. De lo contrario, MySQL debe reservar tres bytes para cada carácter en una columna de utf8 CHAR CHARACTER SET porque esa es la longitud máxima posible. Por ejemplo, MySQL debe reservar 30 bytes para una columna CHAR (10) CHARACTER SET utf8.

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

jspcal
fuente
Casi nunca lo uso CHARy cuando lo hago no está destinado a almacenar caracteres de varios bytes, así que estoy a salvo. ¿ VARCHAREstá seguro de que el límite está definido en caracteres de varios bytes y no en caracteres de un solo byte?
Alix Axel
9
@jspcal: UTF-8 usa un máximo de 4 bytes por carácter, no 3. ¿O MySQL no admite los 4 bytes?
Remy Lebeau
5
@RemyLebeau Tiene razón sobre utf8, pero no para MySQL. Los distintos juegos de caracteres utf8_xxx tienen un máximo de 3 bytes. El utf8mb4_xxx toma caracteres de 4 bytes. dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Buttle Butkus
Con el paso del tiempo, parece que MySQL finalmente usará la versión estándar de 4 bytes (pero todavía no, en el momento de escribir este artículo): dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8 .html .
flow2k
6

32 datos multibytes para la varchar(32)intercalación utf8_unicode_ci, acabo de probar con XAMPP.

1234567890123456789012345678901234567890

Truncar a:

12345678901234567890123456789012

Tenga en cuenta que estos no son caracteres ASCII normales.


fuente
4
En UTF-8, los caracteres ASCII estándar solo se almacenarán en un solo byte; para probar esto realmente, debe usar algunos caracteres multibyte (es decir, no ascii) en su picadura de prueba.
rjmackay
5
Esto está mal, al menos para MySQL 5+. Cuando se especifica el tamaño de columna para varchar o char, se especifica en términos de caracteres. Creo que el tamaño real de una columna VARCHAR (32) sería 32x3 + 1 = 97 bytes.
Buttle Butkus
5
@rjmackay '12345' no son caracteres ASCII estándar. en.wikipedia.org/wiki/…
Alexey Lebedev
7
Inserté 40 caracteres Unicode en DB y se truncaron en 32 caracteres. Pero parece que la gente piensa que usé bytes ascii y me trunqué en 32 bytes. No es de extrañar, tengo votos negativos, jajaja.
USTED
2
@ButtleButkus "Creo que el tamaño real de una columna VARCHAR (32) sería 32x3 + 1 = 97 bytes" Lo haría si lo usa utf8, pero luego obtiene un soporte Unicode roto en MySQL. Debería usar utf8mb4codificación en su lugar, porque hay un máximo de. 4 bytes en un carácter utf-8 , no 3 como en la variante de utf8 de MySQL ...
Stijn de Witt
1

Es mejor usar "char" para tablas de actualización muy frecuentes porque la longitud total de datos de la fila será fija y rápida. Las columnas Varchar hacen que los tamaños de los datos de las filas sean dinámicos. Eso no es bueno para MyISAM, pero no sé nada de InnoDB y otros. Por ejemplo, si tiene una columna de "tipo" muy estrecha, puede ser mejor usar char (2) con el juego de caracteres latin1 para reclamar solo un espacio mínimo.

Empujar
fuente
1
He leído que si CUALQUIER columna de una tabla es varchar, perderá todos los beneficios de tener columnas char. Básicamente, parece que tienes que ir con todos los varchar o todos los char en una tabla para obtener el máximo beneficio. Aunque no sé si es verdad.
Buttle Butkus
Para MyISAM hay algún argumento a favor CHAR. Para InnoDB, están sucediendo tantas otras cosas que el debate sobre "tamaño de fila dinámico / fijo" es esencialmente irrelevante.
Rick James
En mi humilde opinión, el punto importante aquí es que para longitudes muy pequeñas , puede ser beneficioso usarlo CHAR.
ToolmakerSteve
0

Si se conecta a la base de datos utilizando la codificación latin1 (por ejemplo, con PHP) para guardar una cadena PHP UTF8 en una columna MySQL UTF8, tendrá una codificación doble UTF8.

Si la cadena UTF8 $stiene 32 caracteres pero 64 bytes y la columna es VARCHAR(32)UTF8, la codificación doble convertirá la cadena $sen una cadena UTF8 de 64 caracteres que se truncará en la base de datos a sus 32 primeros caracteres correspondientes a los 32 primeros bytes. de $s. Puede terminar pensando que MySQL 5 se comporta como MySQL 4, pero de hecho es una segunda causa del mismo efecto.

Laurent Lyaudet
fuente