Когда я выполнил следующую команду:
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
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.
Если у кого-то возникают проблемы с INNODB / Utf-8, попробуйте поставить UNIQUE
индекс на VARCHAR(256)
поле, переключите его на VARCHAR(255)
, Кажется, 255 является ограничением.
Когда вы достигнете предела. Установите следующее.
utf8
VARCHAR(255)
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
набор символов по умолчанию, который включает в себя поддержку хранения «эмодзи» в базе данных. Если вы используете версию 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 персонажа.
[A-z0-9\-]
персонажи для SEO я использовал latin1_general_ci
который использует только один байт на символ, поэтому столбец может иметь длину 767 байтов. UNIQUE
ключ к тому, чтобы значения SEO были уникальными. Я бы тоже добавил KEY
индекс до оригинальной колонки SEO, чтобы ускорить поиск.