mysql - specified - phpmyadmin#1071-declaracion de clave demasiado larga. la maxima longitud de clave es 767
# 1071-La clave especificada era demasiado larga; La longitud máxima de la clave es de 767 bytes (28)
Cuando ejecuté el siguiente comando:
ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);
Recibí este mensaje de error:
#1071 - Specified key was too long; max key length is 767 bytes
Información sobre column1 y column2:
column1 varchar(20) utf8_general_ci
column2 varchar(500) utf8_general_ci
Creo que varchar(20)
solo requiere 21 bytes, mientras que varchar(500)
solo requiere 501 bytes. Entonces, el total de bytes es 522, menos de 767. Entonces, ¿por qué recibí el mensaje de error?
#1071 - Specified key was too long; max key length is 767 bytes
Creo que varchar (20) solo requiere 21 bytes, mientras que varchar (500) solo requiere 501 bytes. Entonces, el total de bytes es 522, menos de 767. Entonces, ¿por qué recibí el mensaje de error?
UTF8 requiere 3 bytes por carácter para almacenar la cadena, por lo que en su caso 20 + 500 caracteres = 20 * 3 + 500 * 3 = 1560 bytes, que es más de 767 bytes permitidos.
El límite para UTF8 es 767/3 = 255 caracteres , para UTF8mb4 que usa 4 bytes por carácter, es 767/4 = 191 caracteres.
Hay dos soluciones a este problema si necesita usar una columna más larga que el límite:
- Utilice la codificación "más barata" (la que requiere menos bytes por carácter)
En mi caso, necesitaba agregar un índice Único en la columna que contiene la cadena de SEO del artículo, ya que uso solo los caracteres[A-z0-9/-]
para SEO, usélatin1_general_ci
que usa solo un byte por carácter y así la columna puede tener 767 bytes de longitud. - Crea un hash desde tu columna y usa un índice único solo en eso
La otra opción para mí fue crear otra columna que almacenara el hash de SEO, esta columna tendría una claveUNIQUE
para garantizar que los valores de SEO sean únicos. También agregaría el índiceKEY
a la columna original de SEO para acelerar la búsqueda.
¿Qué codificación de caracteres estás usando? Algunos conjuntos de caracteres (como UTF-16, etc.) utilizan más de un byte por carácter.
5 solución:
El límite se elevó en 5.7.7 (MariaDB 10.2.2?). Y se puede aumentar con algún trabajo en 5.6 (10.1).
Si está llegando al límite debido a intentar usar CHARACTER SET utf8mb4. Luego, realice una de las siguientes acciones (cada una tiene un inconveniente) para evitar el error:
⚈ Upgrade to 5.7.7 for 3072 byte limit -- your cloud may not provide this;
⚈ Change 255 to 191 on the VARCHAR -- you lose any values longer than 191 characters (unlikely?);
⚈ ALTER .. CONVERT TO utf8 -- you lose Emoji and some of Chinese;
⚈ Use a "prefix" index -- you lose some of the performance benefits.
⚈ Or... Stay with older version but perform 4 steps to raise the limit to 3072 bytes:
SET GLOBAL innodb_file_format=Barracuda;
SET GLOBAL innodb_file_per_table=1;
SET GLOBAL innodb_large_prefix=1;
logout & login (to get the global values);
ALTER TABLE tbl ROW_FORMAT=DYNAMIC; -- (or COMPRESSED)
- http://mysql.rjweb.org/doc.php/limits#767_limit_in_innodb_indexes
767 bytes es la limitación de prefijo establecida para las tablas InnoDB en la versión 5.6 de MySQL (y versiones anteriores). Tiene 1.000 bytes de longitud para las tablas MyISAM. En la versión 5.7 de MySQL y versiones posteriores, este límite se ha aumentado a 3072 bytes.
También debe tener en cuenta que si establece un índice en un campo grande char o varchar que está codificado en utf8mb4, debe dividir la longitud del prefijo de índice máximo de 767 bytes (o 3072 bytes) por 4, lo que resulta en 191. Esto se debe a La longitud máxima de un carácter utf8mb4 es de cuatro bytes. Para un carácter utf8, serían tres bytes que darían como resultado la longitud máxima del prefijo de índice de 254.
Una opción que tiene es simplemente colocar un límite inferior en sus campos VARCHAR.
Otra opción (según la respuesta a este problema ) es obtener el subconjunto de la columna en lugar de la cantidad total, es decir:
ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );
Modifique la necesidad de obtener la clave para aplicar, pero me pregunto si valdría la pena revisar su modelo de datos con respecto a esta entidad para ver si hay mejoras que le permitan implementar las reglas comerciales previstas sin llegar a la limitación de MySQL.
Aquí está mi respuesta original:
Simplemente suelto la base de datos y recreo así, y el error desaparece:
drop database if exists rhodes; create database rhodes default CHARACTER set utf8 default COLLATE utf8_general_ci;
Sin embargo, no funciona para todos los casos.
En realidad, es un problema el uso de índices en columnas VARCHAR con el conjunto de caracteres utf8
(o utf8mb4
), con columnas VARCHAR que tienen más de una cierta longitud de caracteres. En el caso de utf8mb4
, esa cierta longitud es 191.
Consulte la sección Índice largo en este artículo para obtener más información sobre cómo usar índices largos en la base de datos MySQL: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database-character-set-to-utf8mb4
Basándose en la columna que se proporciona a continuación, esas 2 columnas de cadena variable están utilizando la utf8_general_ci
(el utf8
caracteres utf8
está implícito).
En MySQL, utf8
charset utiliza un máximo de 3 bytes para cada carácter. Por lo tanto, tendría que asignar 500 * 3 = 1500 bytes, que es mucho mayor que lo que permite 767 bytes que MySQL permite. Es por eso que está recibiendo este error 1071.
En otras palabras, debe calcular el recuento de caracteres en función de la representación de bytes del conjunto de caracteres, ya que no todos los conjuntos de caracteres son una representación de un solo byte (como suponía). IE utf8
en MySQL se usa a lo más de 3 bytes por carácter, 767 / 3≈ 255 caracteres, y para utf8mb4
, una representación máxima de 4 bytes, 767 / 4≈191 caracteres.
También se sabe que MySQL.
column1 varchar(20) utf8_general_ci
column2 varchar(500) utf8_general_ci
Cambie CHARSET del campo índice de reclamación a "latin1"
por ejemplo, ALTER TABLE CHANGE myfield myfield varchar (600) CARACTER SET latin1 DEFAULT NULL;
latin1 toma un byte para un carácter en lugar de cuatro
Cuando llegas al límite. Establece lo siguiente.
- INNODB
utf8
VARCHAR(255)
- INNODB
utf8mb4
VARCHAR(191)
En caso de que ejecute Laravel (laravel ahora por defecto es Unicode de 4 bytes, lo que causa esto), puede resolver esto cambiando las siguientes líneas en config / database.php desde
''charset'' => ''utf8mb4'',
''collation'' => ''utf8mb4_unicode_ci'',
 a
''charset'' => ''utf8'',
''collation'' => ''utf8_unicode_ci'',
En mi caso, tuve este problema cuando estaba haciendo una copia de seguridad de una base de datos utilizando los caracteres de entrada / salida de redirección de Linux. Por lo tanto, cambio la sintaxis como se describe a continuación. PS: utilizando un terminal de linux o mac.
Copia de seguridad (sin la redirección)
# mysqldump -u root -p databasename -r bkp.sql
Restaurar (sin la redirección <)
# mysql -u root -p --default-character-set=utf8 databasename
mysql> SET names ''utf8''
mysql> SOURCE bkp.sql
El error "La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes" simplemente desapareció.
Encontré esta consulta útil para detectar qué columnas tenían un índice que viola la longitud máxima:
SELECT
c.TABLE_NAME As TableName,
c.COLUMN_NAME AS ColumnName,
c.DATA_TYPE AS DataType,
c.CHARACTER_MAXIMUM_LENGTH AS ColumnLength,
s.INDEX_NAME AS IndexName
FROM information_schema.COLUMNS AS c
INNER JOIN information_schema.statistics AS s
ON s.table_name = c.TABLE_NAME
AND s.COLUMN_NAME = c.COLUMN_NAME
WHERE c.TABLE_SCHEMA = DATABASE()
AND c.CHARACTER_MAXIMUM_LENGTH > 191
AND c.DATA_TYPE IN (''char'', ''varchar'', ''text'')
He solucionado este problema con:
varchar(200)
Reemplazado con
varchar(191)
todas las varchar que tienen más de 200 las reemplazan por 191 o las establecen texto.
Hemos encontrado este problema al intentar agregar un índice ÚNICO a un campo VARCHAR (255) usando utf8mb4. Si bien el problema ya se ha descrito bien aquí, quería agregar algunos consejos prácticos sobre cómo resolvimos esto y lo resolvimos.
Cuando se usa utf8mb4, los caracteres cuentan como 4 bytes, mientras que bajo utf8, podrían ser de 3 bytes. Las bases de datos InnoDB tienen un límite de que los índices solo pueden contener 767 bytes. Por lo tanto, al usar utf8, puede almacenar 255 caracteres (767/3 = 255), pero al usar utf8mb4, solo puede almacenar 191 caracteres (767/4 = 191).
Es absolutamente capaz de agregar índices regulares para los campos VARCHAR(255)
usando utf8mb4, pero lo que sucede es que el tamaño del índice se trunca en 191 caracteres automáticamente, como unique_key
aquí:
Esto está bien, porque los índices regulares solo se usan para ayudar a MySQL a buscar sus datos más rápidamente. Todo el campo no necesita ser indexado.
Entonces, ¿por qué MySQL trunca el índice automáticamente para los índices regulares, pero lanza un error explícito al intentar hacerlo para índices únicos? Bueno, para que MySQL pueda averiguar si el valor que se está insertando o actualizando ya existe, debe realmente indexar todo el valor y no solo una parte de él.
Al final del día, si desea tener un índice único en un campo, todo el contenido del campo debe encajar en el índice. Para utf8mb4, esto significa reducir sus longitudes de campo VARCHAR a 191 caracteres o menos. Si no necesita utf8mb4 para esa tabla o campo, puede devolverlo a utf8 y mantener sus campos de 255 longitudes.
La respuesta acerca de por qué recibe un mensaje de error ya fue respondida por muchos usuarios aquí. Mi respuesta es acerca de cómo arreglarlo y usarlo como sea.
Consulte en este enlace .
- Abrir cliente MySQL (o cliente MariaDB). Es una herramienta de línea de comandos.
- Le preguntará su contraseña, ingrese su contraseña correcta.
- Seleccione su base de datos usando este comando
use my_database_name;
Base de datos cambiada
-
set global innodb_large_prefix=on;
Consulta OK, 0 filas afectadas (0.00 seg)
-
set global innodb_file_format=Barracuda;
Consulta OK, 0 filas afectadas (0.02 seg)
- Vaya a su base de datos en phpMyAdmin o algo así para una fácil gestión. > Seleccionar base de datos> Ver estructura de tabla> Ir a la pestaña Operaciones . > Cambie ROW_FORMAT a DYNAMIC y guarde los cambios.
- Vaya a la pestaña de estructura de la tabla> Haga clic en el botón Único .
- Hecho. Ahora no debería tener errores.
El problema de esta solución es si exporta db a otro servidor (por ejemplo, de localhost a host real) y no puede usar la línea de comandos MySQL en ese servidor. No puedes hacer que funcione allí.
MySQL asume el peor de los casos para el número de bytes por carácter en la cadena. Para la codificación ''utf8'' de MySQL, eso es 3 bytes por carácter ya que esa codificación no permite caracteres más allá de U+FFFF
. Para la codificación ''utf8mb4'' de MySQL, es de 4 bytes por carácter, ya que eso es lo que MySQL llama UTF-8 real.
Entonces, asumiendo que está usando ''utf8'', su primera columna tomará 60 bytes del índice y la segunda otra 1500.
Para laravel 5.6
Pasos a seguir
- Vaya a
App/Providers/AppServiceProvider.php
. - Agregue esto al proveedor
use Illuminate/Support/Facades/Schema;
en la parte superior - Dentro de la función de arranque Agregue este
Schema::defaultStringLength(191);
que todos disfruten
Para mí, el problema de "# 1071 - La clave especificada era demasiado larga; la longitud máxima de la clave es de 767 bytes" se resolvió después de cambiar la combinación de clave principal / clave única al limitar el tamaño de la columna en 200.
ALTER TABLE `mytable` ADD UNIQUE (
`column1` (200) ,
`column2` (200)
);
Podrías agregar una columna del md5 de columnas largas.
Por favor verifica si sql_mode
es como
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
si es, cambia a
sql_mode=NO_ENGINE_SUBSTITUTION
O
reinicie su servidor cambiando su archivo my.cnf (poniendo lo siguiente)
innodb_large_prefix=on
Si alguien tiene problemas con INNODB / Utf-8 al intentar poner un índice UNIQUE
en un campo VARCHAR(256)
, VARCHAR(255)
a VARCHAR(255)
. Parece que 255 es la limitación.
Si estás creando algo como:
CREATE TABLE IF NOT EXISTS your_table (
id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
name varchar(256) COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (id),
UNIQUE KEY name (name)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;
debería ser algo como
CREATE TABLE IF NOT EXISTS your_table (
id int(7) UNSIGNED NOT NULL AUTO_INCREMENT,
name varchar(256) COLLATE utf8mb4_bin NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1 ROW_FORMAT=FIXED;
pero necesita verificar la singularidad de esa columna desde el código o agregar una nueva columna como MD5 o SHA1 de la columna varchar
Si ha cambiado innodb_log_file_size
recientemente, intente restaurar el valor anterior que funcionó.
Simplemente cambiando utf8mb4
a utf8
al crear tablas, resolví mi problema. Por ejemplo: CREATE TABLE ... DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
para CREATE TABLE ... DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
.
cambia tu colación Puede usar utf8_general_ci que admite casi todos
ejecutar esta consulta antes de su consulta:
SET @@global.innodb_large_prefix = 1;
esto aumentará el límite a 3072 bytes
.
Hice una búsqueda en este tema finalmente conseguí un cambio personalizado
Para MySQL Workbench 6.3.7 Versión Interfaz gráfica está disponible
- Inicie Workbench y seleccione la conexión.
- Vaya a Administración o Instancia y seleccione Archivo de opciones.
- Si Workbench le pide permiso para leer el archivo de configuración y luego lo permite presionando OK dos veces.
- En el lugar central aparece la ventana del archivo de opciones del administrador.
- Vaya a la pestaña InnoDB y verifique innodb_large_prefix si no está marcado en la sección General.
- establezca el valor de la opción innodb_default_row_format en DYNAMIC.
Para las versiones siguientes a 6.3.7, las opciones directas no están disponibles, por lo que debe ir con el símbolo del sistema
- Inicie CMD como administrador.
- Ir al director donde está instalado el servidor mysql La mayoría de los casos está en "C: / Archivos de programa / MySQL / MySQL Server 5.7 / bin", por lo que el comando es "cd /" "cd Archivos de programa / MySQL / MySQL Server 5.7 / bin".
- Ahora ejecute el comando mysql -u userName -p databasecheema Ahora solicitó la contraseña del usuario respectivo. Proporcione la contraseña y entre en el indicador de mysql.
- Tenemos que establecer algunas configuraciones globales, ingrese los comandos a continuación uno por uno global innodb_large_prefix = on; establecer global innodb_file_format = barracuda; establecer global innodb_file_per_table = true;
- Ahora, al final, tenemos que modificar el ROW_FORMAT de la tabla requerida de forma predeterminada, su COMPACTO tenemos que establecerlo en DINÁMICO.
- use el siguiente comando alter table table_name ROW_FORMAT = DYNAMIC;
- Hecho
Solución para Laravel Framework
Según la documentación de Laravel 5.4. * ; app/Providers/AppServiceProvider.php
configurar la longitud de la cadena predeterminada dentro del método de boot
de la app/Providers/AppServiceProvider.php
como se indica a continuación:
use Illuminate/Support/Facades/Schema;
public function boot()
{
Schema::defaultStringLength(191);
}
Explicación de esta solución, dada por la documentación de Laravel 5.4. * :
Laravel usa el
utf8mb4
caracteresutf8mb4
por defecto, que incluye soporte para almacenar "emojis" en la base de datos. Si está ejecutando una versión de MySQL anterior a la versión 5.7.7 o MariaDB anterior a la versión 10.2.2, es posible que deba configurar manualmente la longitud de cadena predeterminada generada por las migraciones para que MySQL pueda crear índices para ellas. Puede configurarlo llamando al métodoSchema::defaultStringLength
dentro de suAppServiceProvider
.Alternativamente, puede habilitar la opción
innodb_large_prefix
para su base de datos. Consulte la documentación de su base de datos para obtener instrucciones sobre cómo habilitar adecuadamente esta opción.
Specified key was too long; max key length is 767 bytes
Recibió ese mensaje porque 1 byte es igual a 1 carácter solo si usa el conjunto de caracteres latin-1
. Si usa utf8
, cada carácter se considerará 3 bytes al definir su columna de clave. Si usa utf8mb4
, cada carácter se considerará de 4 bytes al definir su columna de clave. Por lo tanto, debe multiplicar el límite de caracteres del campo de su clave por 1, 3 o 4 (en mi ejemplo) para determinar el número de bytes que el campo de la clave está tratando de permitir. Si está utilizando uft8mb4, solo puede definir 191 caracteres para un campo de clave principal nativo, InnoDB. Simplemente no violar 767 bytes.