sql >> Base de Datos >  >> RDS >> Mysql

Longitud del índice MySQL varchar

Edición de septiembre de 2021:he estado usando MySQL 8.0 durante un par de años, así que aquí hay información actualizada.

El manual de MySQL ahora tiene una página muy informativa con respecto a la conversión entre utf8mb3 (actualmente también conocido como utf8 ) y utf8mb4 . utf8mb3 está en desuso y se eliminará eventualmente; y cuando se elimina, su alias actual, utf8 , se referirá a utf8mb4 en su lugar.

Con utf8mb3 en desuso , puede almacenar hasta 255 caracteres en un índice, mientras que con utf8mb4 , hasta 191, cuando se usa COMPACT o REDUNDANT formato de fila.

Con COMPRESSED o DYNAMIC formato de fila, los prefijos de clave de índice pueden tener hasta 3072 bytes. Con ellos, puede indexar hasta 1024 caracteres para utf8mb3 y 768 caracteres para utf8mb4 .

A continuación se muestra mi respuesta anterior, que explica parte de la lógica detrás de la cantidad de caracteres puede indexar contra el número de bytes .

Debo revisar mi respuesta debido a mi investigación. Originalmente publiqué esto (citando a mí mismo):

Creo que la respuesta es que no puede saber cuántos caracteres habrá en el índice porque no puede saber cuántos bytes tendrán sus caracteres (a menos que haga algo para excluir los caracteres de varios bytes).

Y no estoy seguro, pero aún podría ser correcto, pero no de la forma en que estaba pensando.

Aquí está la respuesta correcta:

MySQL asume 3 bytes por carácter utf8. 255 caracteres es el tamaño de índice máximo que puede especificar por columna, porque 256x3=768, lo que supera el límite de 767 bytes.

Si no especifica el tamaño del índice, MySQL elige el tamaño máximo (es decir, 255 por columna). No se puede colocar una restricción ÚNICA en una columna utf8 cuya longitud sea mayor que 255, porque un índice único debe contener el valor de celda completo. Pero se puede usar un índice regular:solo indexará los primeros 255 caracteres (¿o los primeros 767 bytes?). Y ahí es donde todavía hay algo de misterio para mí.

El Misterio:Puedo ver por qué MySQL asume 3 bytes por carácter, por seguridad, porque de lo contrario la restricción ÚNICA podría romperse. Pero los documentos parecen sugerir que el índice en realidad tiene un tamaño de bytes, no de caracteres. Supongamos que pones 255 índice char (765 bytes) en un varchar(256 ) columna. Si los caracteres que almacena son todos ASCII, caracteres de 1 byte, como A-Z, a-z, 0-9, entonces puede ajustar la columna completa en el índice de 767 bytes. Y parece que eso es lo que realmente sucedería.

A continuación hay más información de mi respuesta original sobre caracteres, bytes, etc.

Según wikipedia , el carácter UTF-8 puede tener una longitud de 1, 2, 3 o 4 bytes. Pero, de acuerdo con esta documentación de mysql , el tamaño máximo de caracteres es de 3 bytes, por lo que cualquier índice de índice de columna de más de 255 caracteres podría alcanzar ese límite de bytes. Pero según tengo entendido, puede que no. Si la mayoría de sus caracteres están en el rango ASCII, entonces su tamaño de carácter promedio estará más cerca de 1 byte. Si su tamaño de carácter promedio es, por ejemplo, 1,3 bytes (principalmente 1 byte, pero una cantidad significativa de caracteres de 2 a 3 bytes), entonces podría especificar un índice de 767/1,3

Entonces, si está almacenando principalmente caracteres de 1 byte, su límite de caracteres real sería más como:767 / 1.3 =590. Pero resulta que no es así como funciona. 255 caracteres es el límite.

Como se menciona en esta documentación de MySQL ,

Los límites de prefijo se miden en bytes, mientras que la longitud del prefijo en las declaraciones CREATE INDEX se interpreta como una cantidad de caracteres para tipos de datos no binarios (CHAR, VARCHAR, TEXT). Tenga esto en cuenta cuando especifique una longitud de prefijo para una columna que utilice un conjunto de caracteres de varios bytes.

Parece que MySQL está aconsejando a las personas que hagan un cálculo/estimación como acabo de hacer para determinar el tamaño de la clave para una columna varchar. Pero de hecho no puedes especifique un índice superior a 255 para las columnas utf8.

Finalmente, si vuelves a consultar mi segundo enlace, también hay esto:

Cuando la opción de configuración innodb_large_prefix está habilitada, este límite de longitud se eleva a 3072 bytes, para tablas InnoDB que usan los formatos de fila DINÁMICA y COMPRIMIDA.

Entonces parece que puede obtener índices mucho más grandes si lo desea, con un poco de ajuste. Solo asegúrese de que los formatos de fila sean DINÁMICOS o COMPRIMIDO. Probablemente pueda especificar un índice de 1023 o 1024 caracteres en ese caso.

Por cierto, resulta que puede almacenar caracteres de 4 bytes usando [el conjunto de caracteres utf8mb4][4]. El conjunto de caracteres utf8 aparentemente almacena solo [caracteres del "plano 0"][5].

EDITAR:

Intenté crear un índice compuesto en una columna varchar (511) con una columna tinyint (1) y recibí el mensaje de error que decía que el tamaño máximo del índice era de 767 bytes. Esto me hace creer que MySQL asume que las columnas del conjunto de caracteres utf8 contendrán 3 bytes por carácter (el máximo), y le permite usar 255 caracteres como máximo. Pero quizás eso sea solo con índices compuestos. Actualizaré mi respuesta a medida que descubra más. Pero por ahora lo dejo como una edición.