MySQL: указанный ключ был слишком длинным; максимальная длина ключа составляет 767 байт [дубликат]

Если вы получаете это сообщение во время сохранения или компиляции сборки, просто закройте все файлы, а затем откройте любой файл для компиляции и сохранения.

Для меня причина в том, что я переименовал файл, и старый файл все еще был открыт.

382
задан OMG Ponies 23 May 2011 в 22:32
поделиться

27 ответов

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.

295
ответ дан Paweł Gościcki 25 August 2018 в 13:08
поделиться

Если вы создаете что-то вроде:

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;

, это должно быть что-то вроде

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;

, но вам нужно проверить уникальность этого столбца из кода или добавить новый столбец как MD5 или SHA1 столбца varchar

0
ответ дан 10undertiber 25 August 2018 в 13:08
поделиться

Для меня проблема с «# 1071 - указанный ключ была слишком длинной, длина ключа - 767 байт» была решена после изменения комбинации primarykey / uniquekey, ограничив размер столбца на 200.

ALTER TABLE `mytable` ADD UNIQUE (
`column1` (200) ,
`column2` (200)
);
-1
ответ дан Abdul 25 August 2018 в 13:08
поделиться

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

Для Workbench 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 = DYNAMIC;
  7. Выполнено
5
ответ дан Adrian Cid Almaguer 25 August 2018 в 13:08
поделиться

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

  • INNODB utf8 VARCHAR(255)
  • INNODB utf8mb4 VARCHAR(191)
202
ответ дан Aley 25 August 2018 в 13:08
поделиться

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

Согласно Laravel 5.4. * документация ; Вы должны установить длину строки по умолчанию внутри метода

boot

в

app / Providers / AppServiceProvider. php

следующим образом:

use Illuminate\Support\Facades\Schema;

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

Объяснение этого исправления, данное Laravel 5.4. * documentation ;

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

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

22
ответ дан alishaukat 25 August 2018 в 13:08
поделиться

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

36
ответ дан Amber 25 August 2018 в 13:08
поделиться

Я нашел этот запрос полезным при определении того, какие столбцы имели индекс, нарушающий максимальную длину:

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')
1
ответ дан Andrew 25 August 2018 в 13:08
поделиться

Если вы недавно изменили innodb_log_file_size, попытайтесь восстановить предыдущее значение, которое сработало.

0
ответ дан AnkitK 25 August 2018 в 13:08
поделиться
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, primary key. Просто не нарушайте 767 байт.

17
ответ дан Anthony Rutledge 25 August 2018 в 13:08
поделиться

Я думаю, что 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, чтобы ускорить поиск.
21
ответ дан Buksy 25 August 2018 в 13:08
поделиться

В моем случае у меня была эта проблема, когда я создавал резервную копию базы данных с использованием выходных / входных символов перенаправления linux. Поэтому я изменяю синтаксис, как описано ниже. PS: использование терминала linux или mac.

Резервное копирование (без> перенаправления)

# mysqldump -u root -p databasename -r bkp.sql

Восстановление (без & lt; редирект)

# mysql -u root -p --default-character-set=utf8 databasename
mysql> SET names 'utf8'
mysql> SOURCE bkp.sql

Ошибка «Указанный ключ был слишком длинным, максимальная длина ключа - 767 байт» исчезла.

0
ответ дан Cassio Seffrin 25 August 2018 в 13:08
поделиться

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

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

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
ответ дан Châu Hồng Lĩnh 25 August 2018 в 13:08
поделиться

Если вы запустите Laravel (теперь для laravel по умолчанию используется 4-байтовый Unicode), вы можете решить это, изменив следующие строки в config / database.php из

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

 на

'charset' => 'utf8',
'collation' => 'utf8_unicode_ci',
-2
ответ дан despotbg 25 August 2018 в 13:08
поделиться

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

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

Другими словами, вам нужно вычислить количество символов на основе байтового представления charset, так как не каждая кодировка представляет собой однобайтовое представление (как вы предполагали). 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
2
ответ дан Devy 25 August 2018 в 13:08
поделиться

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

15
ответ дан diyism 25 August 2018 в 13:08
поделиться

запустите этот запрос перед вашим запросом:

SET @@global.innodb_large_prefix = 1;

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

33
ответ дан Fábio Batista 25 August 2018 в 13:08
поделиться

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

varchar(200) 

, замененного на

varchar(191)

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

1
ответ дан flik 25 August 2018 в 13:08
поделиться

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

Обратитесь к этой ссылке .

  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;

Query OK, 0 строк затронуты (0,02 сек)

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

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

12
ответ дан huan son 25 August 2018 в 13:08
поделиться

Для laravel 5.6

Шаги к следующему

  1. Перейти к app \ Providers \ AppServiceProvider.php
  2. Добавить это в провайдер || (Дон 't include pipe) использовать Illuminate \ Support \ Facades \ Schema;
  3. Внутри функции загрузки Добавить это || (Не включать конвейер) Schema :: defaultStringLength (191);

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

0
ответ дан Iraniya Naynesh 25 August 2018 в 13:08
поделиться

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

0
ответ дан MajidJafari 25 August 2018 в 13:08
поделиться

Мы столкнулись с этой проблемой при попытке добавить индекс 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 здесь:

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

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

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

11
ответ дан maknz 25 August 2018 в 13:08
поделиться

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

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

143
ответ дан morganwahl 25 August 2018 в 13:08
поделиться

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

5
ответ дан Nids Barthwal 25 August 2018 в 13:08
поделиться

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

352
ответ дан PinkTurtle 25 August 2018 в 13:08
поделиться

Измените CHARSET поля индекса жалобы на «latin1», то есть ALTER TABLE tbl CHANGE myfield myfield varchar (600) CHARACTER SET latin1 DEFAULT NULL; latin1 принимает один байт за один символ вместо четырех

0
ответ дан Stan Holodnak 25 August 2018 в 13:08
поделиться

Убедитесь, что sql_mode подобен

sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

, если он есть, измените на

sql_mode=NO_ENGINE_SUBSTITUTION

ИЛИ

перезапустите сервер, изменив свой файл my.cnf (установка следующий)

innodb_large_prefix=on
1
ответ дан YakovL 25 August 2018 в 13:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: