# 1071 - Указанный ключ был слишком длинным; максимальная длина ключа 767 байт - PullRequest
470 голосов
/ 29 ноября 2009

Когда я выполнил следующую команду:

ALTER TABLE `mytable` ADD UNIQUE (
`column1` ,
`column2`
);

Я получил это сообщение об ошибке:

#1071 - Specified key was too long; max key length is 767 bytes

Информация о столбце 1 и столбце 2:

column1 varchar(20) utf8_general_ci
column2  varchar(500) utf8_general_ci

Я думаю, varchar(20) требуется всего 21 байт, а varchar(500) - только 501 байт. Таким образом, общее количество байтов составляет 522, а не 767. Так почему я получил сообщение об ошибке?

#1071 - Specified key was too long; max key length is 767 bytes

Ответы [ 32 ]

402 голосов
/ 29 ноября 2009

767 байт - это ограничение указанного префикса для таблиц InnoDB в MySQL версии 5.6 (и предыдущих версиях). Это длина 1000 байтов для таблиц MyISAM. В версии MySQL 5.7 и выше этот предел был увеличен до 3072 байт.

Вы также должны знать, что если вы устанавливаете индекс для большого поля типа char или varchar, кодируемого utf8mb4, вы должны разделить максимальную длину префикса индекса 767 байт (или 3072 байт) на 4, что приведет к 191. Это связано с тем, что максимальная длина символа utf8mb4 составляет четыре байта. Для символа utf8 это будет три байта, что приведет к максимальной длине префикса индекса 254.

Один из вариантов, который у вас есть, это просто установить нижний предел для ваших полей VARCHAR.

Другой вариант (согласно ответу на эту проблему ) - получить подмножество столбца, а не всю сумму, т. Е .:

ALTER TABLE `mytable` ADD UNIQUE ( column1(15), column2(200) );

Настройте, чтобы получить ключ для применения, но мне интересно, стоит ли пересматривать вашу модель данных относительно этой сущности, чтобы увидеть, есть ли улучшения, которые позволят вам реализовать намеченные бизнес-правила, не затрагивая MySQL ограничение.

383 голосов
/ 29 мая 2013

Если у кого-то возникают проблемы с INNODB / Utf-8, пытающимся поместить индекс UNIQUE в поле VARCHAR(256), переключите его на VARCHAR(255). Кажется, 255 является ограничением.

279 голосов
/ 17 июля 2015

Когда вы достигнете предела. Установите следующее.

  • INNODB utf8 VARCHAR(255)
  • INNODB utf8mb4 VARCHAR(191)
146 голосов
/ 19 марта 2014

MySQL предполагает наихудший случай для количества байтов на символ в строке. Для кодировки MySQL 'utf8' это 3 байта на символ, поскольку эта кодировка не допускает символы, превышающие U+FFFF. Для кодировки MySQL 'utf8mb4' это 4 байта на символ, поскольку именно это MySQL называет фактическим UTF-8.

Итак, если вы используете utf8, ваш первый столбец займет 60 байтов индекса, а второй - 1500.

47 голосов
/ 05 апреля 2014

выполнить этот запрос перед вашим запросом:

SET @@global.innodb_large_prefix = 1;

это увеличит лимит до 3072 bytes.

37 голосов
/ 29 ноября 2009

Какую кодировку символов вы используете? Некоторые наборы символов (например, UTF-16 и т. Д.) Используют более одного байта на символ.

32 голосов
/ 23 июля 2017

Решение для Laravel Framework

Согласно Laravel 5.4. * Документация ; Вы должны установить длину строки по умолчанию в методе boot файла app/Providers/AppServiceProvider.php следующим образом:

use Illuminate\Support\Facades\Schema;

public function boot() 
{
    Schema::defaultStringLength(191); 
}

Объяснение этого исправления, данное Laravel 5.4. * Документация :

Laravel по умолчанию использует набор символов utf8mb4, который включает в себя поддержку хранения "emojis" в базе данных. Если вы используете версию MySQL, более раннюю, чем версия 5.7.7, или MariaDB, более раннюю, чем версия 10.2.2, вам может потребоваться вручную настроить длину строки по умолчанию, создаваемую миграциями, чтобы MySQL создавал для них индексы. Вы можете настроить это, вызвав метод Schema::defaultStringLength в вашем AppServiceProvider.

Кроме того, вы можете включить опцию innodb_large_prefix для вашего база данных. Обратитесь к документации вашей базы данных для получения инструкций по как правильно включить эту опцию.

23 голосов
/ 23 декабря 2016

Я думаю, что varchar (20) требует только 21 байт, тогда как только varchar (500) требуется 501 байт. Таким образом, общее количество байтов составляет 522, а не 767. Так почему я получил сообщение об ошибке?

UTF8 требует 3 байта на символ для хранения строки, поэтому в вашем случае 20 + 500 символов = 20 * 3 + 500 * 3 = 1560 байтов, что составляет более разрешено 767 байт.

Предел для UTF8 составляет 767/3 = 255 символов , для UTF8mb4, который использует 4 байта на символ, это 767/4 = 191 символов.


Существует два варианта решения этой проблемы, если вам нужно использовать более длинный столбец, чем предел:

  1. Использовать "более дешевую" кодировку (ту, которая требует меньше байтов на символ)
    В моем случае мне нужно было добавить уникальный индекс для столбца, содержащего строку статьи SEO, поскольку я использую только [A-z0-9\-] символов для SEO, я использовал latin1_general_ci, который использует только один байт на символ, и поэтому столбец может иметь длину 767 байтов.
  2. Создать хеш из вашего столбца и использовать уникальный индекс только для этого
    Другой вариант для меня - создать еще один столбец, в котором будет храниться хэш SEO, в этом столбце будет ключ UNIQUE, чтобы гарантировать уникальность значений SEO. Я бы также добавил индекс KEY в исходный столбец SEO, чтобы ускорить поиск.
19 голосов
/ 30 июля 2016

Ответ о том, почему вы получили сообщение об ошибке, уже был дан ответ многим пользователям здесь. Мой ответ о том, как исправить и использовать его как есть.

Ссылка на эту ссылку .

  1. Открыть клиент MySQL (или клиент MariaDB). Это инструмент командной строки.
  2. Он спросит ваш пароль, введите правильный пароль.
  3. Выберите вашу базу данных с помощью этой команды use my_database_name;

База данных изменена

  1. set global innodb_large_prefix=on;

Запрос в порядке, затронуто 0 строк (0,00 с)

  1. set global innodb_file_format=Barracuda;

Запрос в порядке, затронуто 0 строк (0,02 с)

  1. Перейдите в свою базу данных на phpMyAdmin или что-то в этом роде для удобного управления. > Выберите базу данных> Просмотр таблицы Структура > Перейдите на вкладку Операции . > Измените ROW_FORMAT на DYNAMIC и сохраните изменения.
  2. Перейти к вкладке структуры таблицы вкладка> Нажать Уникальную кнопку .
  3. Готово. Теперь он не должен иметь ошибок.

Проблема этого исправления заключается в том, что вы экспортируете db на другой сервер (например, с локального хоста на реальный хост) и не можете использовать командную строку MySQL на этом сервере. Вы не можете заставить его работать там.

17 голосов
/ 13 октября 2015
Specified key was too long; max key length is 767 bytes

Вы получили это сообщение, потому что 1 байт равен 1 символу, только если вы используете набор символов latin-1. Если вы используете utf8, каждый символ будет рассматриваться как 3 байта при определении ключевого столбца. Если вы используете utf8mb4, каждый символ будет считаться 4 байтом при определении ключевого столбца. Таким образом, вам нужно умножить ограничение на количество символов в вашем ключевом поле на 1, 3 или 4 (в моем примере), чтобы определить количество байтов, которое поле ключа пытается разрешить. Если вы используете uft8mb4, вы можете определить только 191 символ для собственного поля первичного ключа InnoDB. Только не нарушайте 767 байт.

...