# 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 ]

15 голосов
/ 25 февраля 2011

вы можете добавить столбец md5 длинных столбцов

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

Мы столкнулись с этой проблемой при попытке добавить индекс UNIQUE в поле VARCHAR (255) с помощью utf8mb4. Несмотря на то, что проблема уже хорошо изложена, я хотел бы добавить несколько практических советов, как мы это выяснили и решили.

При использовании utf8mb4 символы считаются как 4 байта, тогда как при utf8 они могут быть как 3 байта. Базы данных InnoDB имеют ограничение, что индексы могут содержать только 767 байтов. Поэтому при использовании utf8 вы можете хранить 255 символов (767/3 = 255), но при использовании utf8mb4 вы можете хранить только 191 символ (767/4 = 191).

Вы абсолютно можете добавить обычные индексы для VARCHAR(255) полей, используя utf8mb4, но в этом случае размер индекса автоматически усекается до 191 символа - как unique_key здесь:

Sequel Pro screenshot showing index truncated at 191 characters

Это хорошо, потому что обычные индексы просто используются, чтобы помочь MySQL быстрее искать ваши данные. Целое поле не нужно индексировать.

Итак, почему MySQL автоматически усекает индекс для обычных индексов, но выдает явную ошибку при попытке сделать это для уникальных индексов? Что ж, для того, чтобы MySQL мог определить, существует ли уже добавляемое или обновляемое значение, ему нужно индексировать целое значение, а не только его часть.

В конце дня, если вы хотите иметь уникальный индекс для поля, все содержимое поля должно вписываться в индекс. Для utf8mb4 это означает уменьшение длины поля VARCHAR до 191 символа или менее. Если вам не нужен utf8mb4 для этой таблицы или поля, вы можете сбросить его обратно до utf8 и сохранить свои поля длиной 255.

9 голосов
/ 15 февраля 2017

Вот мой оригинальный ответ:

Я просто удаляю базу данных и воссоздаю вот так, и ошибка исчезла:

drop database if exists rhodes; create database rhodes default CHARACTER set utf8 default COLLATE utf8_general_ci;

Однако, это не работает для всех случаев.

На самом деле проблема заключается в использовании индексов для столбцов VARCHAR с набором символов utf8 (или utf8mb4) со столбцами VARCHAR, длина которых превышает определенную длину символов. В случае utf8mb4 эта определенная длина равна 191.

Пожалуйста, обратитесь к разделу Длинный индекс в этой статье для получения дополнительной информации о том, как использовать длинные индексы в базе данных MySQL: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database-character-set-to-utf8mb4

7 голосов
/ 29 сентября 2016

Я провел некоторый поиск по этой теме, наконец-то получил некоторые пользовательские изменения

Для MySQL верстак 6.3.7 Версия Доступна графическая межфазная среда

  1. Запустите Workbench и выберите соединение.
  2. Перейдите в Управление или Экземпляр и выберите Файл опций.
  3. Если Workbench спросит у вас разрешение на чтение файла конфигурации, а затем разрешите его, нажав OK двараз.
  4. По центру появляется окно файла параметров администратора.
  5. Перейдите на вкладку InnoDB и проверьте innodb_large_prefix, если он не отмечен в разделе «Общие».
  6. установите значение параметра innodb_default_row_formatв DYNAMIC.

Для версий ниже 6.3.7 прямые опции недоступны, поэтому необходимо использовать командную строку

  1. Запустить CMD от имени администратора.
  2. Перейти к директору, где установлен сервер mysql. В большинстве случаев это по адресу "C: \ Program Files \ MySQL \ MySQL Server 5.7 \ bin", поэтому команда "cd \" "cd Program Files \ MySQL \ MySQL Server 5.7 \ bin ".
  3. Теперь выполните команду mysql -u userName -p databasescheema Теперь он запрашивает пароль соответствующего пользователя.Введите пароль и введите приглашение mysql.
  4. Мы должны установить некоторые глобальные настройки, ввести нижеприведенные команды одну за другой set global innodb_large_prefix = on;установить глобальный innodb_file_format = barracuda;set global innodb_file_per_table = true;
  5. Теперь, когда мы в последний раз должны изменить ROW_FORMAT требуемой таблицы, по умолчанию ее COMPACT мы должны установить в DYNAMIC.
  6. использовать следующую команду alter table table_name ROW_FORMAT= ДИНАМИЧНЫЙ;
  7. Готово
7 голосов
/ 11 октября 2018

5 обходных путей:

Предел был повышен в 5.7.7 (MariaDB 10.2.2?). И это может быть увеличено с некоторой работой в 5.6 (10.1).

Если вы превышаете лимит из-за попытки использовать CHARACTER SET utf8mb4. Затем выполните одно из следующих действий (у каждого есть недостаток), чтобы избежать ошибки:

⚈  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

7 голосов
/ 09 апреля 2018

Я исправил эту проблему с помощью:

varchar(200) 

заменено на

varchar(191)

все varchar, которые имеют более 200, заменяют их 191 или устанавливают их текст.

5 голосов
/ 29 мая 2017

изменить параметры сортировки. Вы можете использовать utf8_general_ci , который поддерживает почти все

4 голосов
/ 26 июня 2018

Для Laravel 5,7 или 5,6 или 5,8

Шаги для следования

  1. Перейти к App\Providers\AppServiceProvider.php.
  2. Добавьте это к поставщику use Illuminate\Support\Facades\Schema; в топе.
  3. Внутри функции загрузки Добавить это Schema::defaultStringLength(191);

вот и все, Наслаждайтесь.

3 голосов
/ 21 июля 2018

Просто изменение utf8mb4 на utf8 при создании таблиц решило мою проблему. Например: CREATE TABLE ... DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; до CREATE TABLE ... DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;.

2 голосов
/ 02 декабря 2015

Исходя из приведенного ниже столбца, эти 2 столбца переменной строки используют сопоставление utf8_general_ci (подразумевается utf8 кодировка).

В MySQL utf8 charset использует максимум 3 байта для каждого символа. Таким образом, потребуется выделить 500 * 3 = 1500 байт, что намного больше, чем 767 байт, которые позволяет MySQL. Вот почему вы получаете эту ошибку 1071.

Другими словами, вам нужно вычислить количество символов на основе байтового представления кодировки, поскольку не каждая кодировка является однобайтовым представлением (как вы предполагали). I.E. utf8 в MySQL использует не более 3 байтов на символ, 767 / 3≈255 символов, а для utf8mb4 - максимально 4-байтовое представление, 767 / 4≈191 символов.

Также известно, что MySQL

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