Когда я выполнил следующую команду:
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
mysql
byte
varchar
mysql-error-1071
Стивен
источник
источник
Ответы:
767 байт - заявленное ограничение префикса для таблиц InnoDB в MySQL версии 5.6 (и предыдущих версиях). Это длина 1000 байтов для таблиц MyISAM. В версии MySQL 5.7 и выше этот предел был увеличен до 3072 байт.
Вы также должны знать, что если вы устанавливаете индекс для большого поля типа char или varchar, кодируемого utf8mb4, вы должны разделить максимальную длину префикса индекса 767 байт (или 3072 байт) на 4, что приведет к 191. Это потому, что максимальная длина символа utf8mb4 составляет четыре байта. Для символа utf8 это будет три байта, что приведет к максимальной длине префикса индекса 254.
Один из вариантов, который у вас есть, это просто установить нижний предел для ваших полей VARCHAR.
Другой вариант (согласно ответу на эту проблему ) состоит в том, чтобы получить подмножество столбца, а не всю сумму, то есть:
Настройте его так, чтобы получить ключ для применения, но мне интересно, стоит ли пересматривать вашу модель данных относительно этой сущности, чтобы увидеть, есть ли улучшения, которые позволят вам реализовать намеченные бизнес-правила, не нарушая ограничения MySQL.
источник
utf8mb4
набор символов Mysql (который остальной мир называет utf8) требует (максимум) 4 байта на символ, вы можете индексировать только доVARCHAR(191)
.utf8
Набор символов Mysql (который остальной мир называет неработающим) требует максимум 3 байта на символ, поэтому, если вы используете его (чего не следует ), вы можете индексировать доVARCHAR(255)
Если у кого-то есть проблемы с INNODB / Utf-8, пытающимся поместить
UNIQUE
индекс вVARCHAR(256)
поле, переключите его наVARCHAR(255)
. Кажется, 255 является ограничением.источник
3*255 = 765 < 767
.utf8
, который, к сожалению, не работает. Он может кодировать символы только в основной многоязычной плоскости. Вы получите проблемы с персонажами, выходящими за рамки этого. Например, те персонажи Emoji, которые они добавляли, выпадают из этого, я думаю. Поэтому вместо того, чтобы переключаться наVARCHAR(255)
, переключаться наVARCHAR(191)
и переключать кодировку наutf8mb4
(что на самом деле просто utf8, но MySql хотел сохранить обратно. Compat).Когда вы достигнете предела. Установите следующее.
utf8
VARCHAR(255)
utf8mb4
VARCHAR(191)
источник
utf8mb4
ограничение (которое является наиболее используемой кодировкой для новых баз данных, так как она принимает эмодзи / и т. Д.).ENGINE=InnoDB DEFAULT CHARSET=utf8
в концеCREATE TABLE
оператора, я смог получитьVARCHAR(255)
первичный ключ. Спасибо.MySQL предполагает худший случай для количества байтов на символ в строке. Для кодировки MySQL 'utf8' это 3 байта на символ, так как эта кодировка не допускает символов за пределами
U+FFFF
. Для кодировки MySQL 'utf8mb4' это 4 байта на символ, поскольку именно это MySQL называет фактическим UTF-8.Итак, если вы используете utf8, ваш первый столбец займет 60 байтов индекса, а второй - 1500.
источник
запустите этот запрос перед вашим запросом:
это увеличит лимит до
3072 bytes
.источник
innodb_file_format
должно бытьBARRACUDA
и На уровне таблицы вы должны использоватьROW_FORMAT=DYNAMIC
илиROW_FORMAT=COMPRESSED
. См. Комментарий @ cwd выше с руководством.Решение для Laravel Framework
Согласно документации Laravel 5.4. * ; Вы должны установить длину строки по умолчанию внутри
boot
методаapp/Providers/AppServiceProvider.php
файла следующим образом:Объяснение этого исправления, приведенное в документации Laravel 5.4. * :
источник
Какую кодировку символов вы используете? Некоторые наборы символов (например, UTF-16 и т. Д.) Используют более одного байта на символ.
источник
20 * 4 + 1
байты, а столбец из 500 символов -500 * 4 + 2
байтыVARCHAR(256)
столбца сUNIQUE
индексом изменение параметров сортировки для меня не имело никакого эффекта, как для @Andresch. Тем не менее, сокращение длины с 256 до 255 действительно решило эту проблему. Я не понимаю почему, так как 767 / макс. 4 байта на символ дадут максимум 191?255*3 = 765; 256*3 = 768
, Оказывается , ваш сервер был asssuming 3 байта на символ, @ АрьянUTF8 требует 3 байта на символ для хранения строки, поэтому в вашем случае 20 + 500 символов = 20 * 3 + 500 * 3 = 1560 байтов, что больше допустимого 767 байтов.
Предел для UTF8 составляет 767/3 = 255 символов , для UTF8mb4, который использует 4 байта на символ, это 767/4 = 191 символ.
Есть два решения этой проблемы, если вам нужно использовать более длинный столбец, чем предел:
В моем случае мне нужно было добавить уникальный индекс для столбца, содержащего строку статьи SEO, поскольку я использую только
[A-z0-9\-]
символы для SEO, я использовал,latin1_general_ci
который использует только один байт на символ и поэтому столбец может иметь длину 767 байтов.. Другой вариант для меня - создать еще один столбец, в котором будет храниться хэш SEO, в этом столбце будет
UNIQUE
ключ, обеспечивающий уникальность значений SEO. Я также добавил быKEY
индекс к оригинальной колонке SEO, чтобы ускорить поиск.источник
Ответ о том, почему вы получаете сообщение об ошибке, уже был дан ответ многим пользователям здесь. Мой ответ о том, как исправить и использовать его как есть.
Обратитесь с этой ссылки .
use my_database_name;
set global innodb_large_prefix=on;
set global innodb_file_format=Barracuda;
Проблема этого исправления заключается в том, что вы экспортируете db на другой сервер (например, с локального хоста на реальный хост) и не можете использовать командную строку MySQL на этом сервере. Вы не можете заставить это работать там.
источник
Вы получили это сообщение, потому что 1 байт равен 1 символу, только если вы используете
latin-1
набор символов. Если вы используетеutf8
, каждый символ будет рассматриваться как 3 байта при определении ключевого столбца. Если вы используетеutf8mb4
, каждый символ будет рассматриваться как 4 байта при определении ключевого столбца. Таким образом, вам нужно умножить ограничение на количество символов в вашем ключевом поле на 1, 3 или 4 (в моем примере), чтобы определить количество байтов, которое поле ключа пытается разрешить. Если вы используете uft8mb4, вы можете определить только 191 символ для собственного поля первичного ключа InnoDB. Только не нарушайте 767 байт.источник
Замените
utf8mb4
наutf8
в вашем файле импорта.источник
Вы можете добавить столбец md5 длинных столбцов
источник
Мы столкнулись с этой проблемой при попытке добавить индекс 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 и сохранить свои поля длиной 255.
источник
Вот мой оригинальный ответ:
Тем не менее, это не работает для всех случаев.
На самом деле это проблема использования индексов для столбцов VARCHAR с набором символов
utf8
(илиutf8mb4
) со столбцами VARCHAR, длина которых превышает определенную длину символов. В случаеutf8mb4
, эта определенная длина составляет 191.Пожалуйста, обратитесь к разделу Длинный индекс в этой статье для получения дополнительной информации о том, как использовать длинные индексы в базе данных MySQL: http://hanoian.com/content/index.php/24-automate-the-converting-a-mysql-database- Символьный набор к utf8mb4
источник
5 обходных путей:
Лимит был повышен в 5.7.7 (MariaDB 10.2.2?). И это может быть увеличено с некоторой работой в 5.6 (10.1).
Если вы превышаете лимит из-за попытки использовать CHARACTER SET utf8mb4. Затем выполните одно из следующих действий (у каждого есть недостаток), чтобы избежать ошибки:
- http://mysql.rjweb.org/doc.php/limits#767_limit_in_innodb_indexes
источник
Я исправил эту проблему с:
заменено на
все varchar, у которых есть больше чем 200, заменяют их 191 или устанавливают их текст.
источник
Я сделал некоторые поиски по этой теме, наконец, получил некоторые пользовательские изменения
Для MySQL верстак 6.3.7 Версия Доступна графическая межфаза
Для версий ниже 6.3.7 прямые параметры недоступны, поэтому необходимо использовать командную строку
источник
set global innodb_default_row_format = DYNAMIC;
я вижу это сообщение: ОШИБКА 1193 (HY000): неизвестная системная переменная 'innodb_default_row_format'Для Laravel 5,7 до 6,0
Шаги, чтобы следовать
App\Providers\AppServiceProvider.php
.use Illuminate\Support\Facades\Schema;
в топе.Schema::defaultStringLength(191);
это все, наслаждайтесь.
источник
email
уникальные вещи , но вы должны хэшировать электронную почту и делать ее уникальной. В отличие от необработанных строковых данных, хэши имеют фиксированную ширину и могут быть проиндексированы и сделаны уникальными без проблем. Вместо того, чтобы понимать проблему, вы распространяете ужасные практики, которые не масштабируются.измените свою сортировку. Вы можете использовать utf8_general_ci, который поддерживает почти все
источник
Просто переход
utf8mb4
наutf8
создание таблиц решил мою проблему. Например:CREATE TABLE ... DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
кCREATE TABLE ... DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
.источник
Чтобы исправить это, это работает для меня как шарм.
источник
Основываясь на приведенном ниже столбце, эти 2 столбца переменной строки используют параметры
utf8_general_ci
сортировки (utf8
подразумевается charset).В MySQL
utf8
кодировка использует максимум 3 байта для каждого символа. Таким образом, потребуется выделить 500 * 3 = 1500 байт, что намного больше, чем 767 байт, которые позволяет MySQL. Вот почему вы получаете эту ошибку 1071.Другими словами, вам нужно вычислить количество символов на основе байтового представления кодировки, поскольку не каждая кодировка является однобайтовым представлением (как вы предполагали). IE
utf8
в MySQL использует максимум 3 байта на символ, 767 / 3≈255 персонажи, а дляutf8mb4
, самое большее, 4-байтовое представление, 767 / 4≈191 символов.Также известно, что MySQL
источник
Я нашел этот запрос полезным для определения того, какие столбцы имеют индекс, нарушающий максимальную длину:
источник
Пожалуйста, проверьте, если
sql_mode
это какесли это так, измените на
ИЛИ
перезагрузите сервер, изменив файл my.cnf (добавив следующее)
источник
В моем случае у меня была эта проблема, когда я делал резервные копии базы данных, используя символы ввода / вывода перенаправления linux. Поэтому я меняю синтаксис, как описано ниже. PS: используя терминал Linux или Mac.
Резервное копирование (без перенаправления>)
Восстановить (без <перенаправления)
Ошибка "Указанный ключ был слишком длинным; максимальная длина ключа - 767 байт" просто исчезла.
источник
Длина индекса и MySQL / MariaDB
Laravel по умолчанию использует набор символов utf8mb4 , который включает поддержку для хранения «emojis» в базе данных. Если вы используете версию MySQL, более раннюю, чем версия 5.7.7, или MariaDB, более раннюю, чем версия 10.2.2, вам может потребоваться вручную настроить длину строки по умолчанию, создаваемую миграциями, чтобы MySQL создавал для них индексы. Вы можете настроить это, вызвав метод Schema :: defaultStringLength в вашем AppServiceProvider:
Кроме того, вы можете включить опцию innodb_large_prefix для вашей базы данных. Обратитесь к документации вашей базы данных для получения инструкций о том, как правильно включить эту опцию.
Ссылка из блога: https://www.scratchcode.io/specified-key-too-long-error-in-laravel/
Ссылка из Официальной документации Laravel: https://laravel.com/docs/5.7/migrations
источник
Если вы создаете что-то вроде:
это должно быть что-то вроде
но вам нужно проверить уникальность этого столбца из кода или добавить новый столбец как MD5 или SHA1 столбца varchar
источник
Из-за ограничений префикса эта ошибка произойдет. 767 байт - это заявленное ограничение префикса для таблиц InnoDB в версиях MySQL до 5.7. Это длина 1000 байтов для таблиц MyISAM. В версии MySQL 5.7 и выше этот предел был увеличен до 3072 байт.
Выполнение следующих действий в службе, сообщающей вам об ошибке, должно решить вашу проблему. Это должно быть запущено в MYSQL CLI.
источник
Измените CHARSET поля жалобного индекса на "latin1",
т.е. ALTER TABLE tbl CHANGE myfield myfield varchar (600) CHARACTER SET latin1 DEFAULT NULL;
latin1 занимает один байт для одного символа вместо четырех
источник
Если вы
innodb_log_file_size
недавно изменились , попробуйте восстановить предыдущее значение, которое сработало.источник