#1071 - указанный ключ был слишком длинным; максимальная длина ключа составляет 767 байт

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

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

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

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

информация о column1 и column2:

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

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) );

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


Если у кого-то возникли проблемы с INNODB / Utf-8, пытаясь поставить на


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

  • InnoDB в utf8 VARCHAR(255)
  • InnoDB в utf8mb4 VARCHAR(191)

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

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


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

SET @@global.innodb_large_prefix = 1;

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


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


Решение Для 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 для вашего база данных. Инструкции по использованию см. В документации базы данных как правильно включить эту опцию.


Я думаю, что 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, чтобы ускорить поиск.

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 байт.


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


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

С этой ссылке.

  1. открыть клиент MySQL (или клиент MariaDB). Это инструмент командной строки.
  2. он спросит ваш пароль, введите правильный пароль.
  3. выберите базу данных с помощью этой команды use my_database_name;
.
  • сделано. Теперь он не должен иметь ошибок.
  • проблема этого исправления заключается в том, что вы экспортируете БД на другой сервер (например, с localhost на реальный хост), и вы не можете использовать командную строку MySQL на этом сервере. Вы не можете заставить его работать там.


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


    вот мой первоначальный ответ:

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

    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


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

    для MySQL workbench версии 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 Program Files\MySQL\MySQL Server 5.7\bin".
    3. Теперь запустите команду mysql - u имя пользователя-P databasescheema Теперь он запросил пароль соответствующего пользователя. Введите пароль и введите запрос mysql.
    4. мы должны установить некоторые глобальные настройки введите ниже команды один за другим установить глобальный innodb_large_prefix=on; установить глобальный innodb_file_format=Барракуда; установить глобальный innodb_file_per_table=true;
    5. сейчас в последнее, что мы должны изменить ROW_FORMAT требуемой таблицы по умолчанию его компактность, мы должны установить его в динамический.
    6. используйте следующую команду alter table table_name ROW_FORMAT=динамический;
    7. сделал

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


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

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

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

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

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

    я исправил эту проблему с:

    varchar(200) 
    

    заменить

    varchar(191)
    

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


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

    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')
    

    пожалуйста, проверьте, если sql_mode как

    sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
    

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

    sql_mode=NO_ENGINE_SUBSTITUTION
    

    или

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

    innodb_large_prefix=on
    

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


    изменить кодировку поля индекса жалоб на "latin1"
    т. е. изменить таблицу tbl изменить myfield myfield varchar (600) Набор символов latin1 по умолчанию NULL;
    latin1 принимает один байт за один символ вместо четырех


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

    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


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


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

    резервное копирование (без > редирект)

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

    восстановить (без

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

    ошибка "указанный ключ был слишком длинным; максимальная длина ключа составляет 767 байт" просто исчез.


    для laravel 5.6

    шаги, чтобы следовать

    1. перейдите в раздел app\Providers\AppServiceProvider.в PHP
    2. добавьте это к провайдеру / / (не включайте конвейер) используйте Illuminate\Support\Facades\Schema;
    3. внутри функции загрузки добавьте эту схему / / (не включать конвейер):: defaultStringLength (191);

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


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

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

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

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

     к

    'charset' => 'utf8',
    'collation' => 'utf8_unicode_ci',