#1071 - Указанный ключ был слишком длинным; максимальная длина ключа 1000 байтов
Я знаю, что вопросы с этим названием уже были даны ответы, но, пожалуйста, читайте дальше. Я прочитал внимательно все остальные вопросы / ответы по этой ошибке, прежде чем писать.
Я получаю вышеуказанную ошибку для следующего запроса:
CREATE TABLE IF NOT EXISTS `pds_core_menu_items` (
`menu_id` varchar(32) NOT NULL,
`parent_menu_id` int(32) unsigned DEFAULT NULL,
`menu_name` varchar(255) DEFAULT NULL,
`menu_link` varchar(255) DEFAULT NULL,
`plugin` varchar(255) DEFAULT NULL,
`menu_type` int(1) DEFAULT NULL,
`extend` varchar(255) DEFAULT NULL,
`new_window` int(1) DEFAULT NULL,
`rank` int(100) DEFAULT NULL,
`hide` int(1) DEFAULT NULL,
`template_id` int(32) unsigned DEFAULT NULL,
`alias` varchar(255) DEFAULT NULL,
`layout` varchar(255) DEFAULT NULL,
PRIMARY KEY (`menu_id`),
KEY `index` (`parent_menu_id`,`menu_link`,`plugin`,`alias`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
У кого-нибудь есть идеи, почему и как это исправить? Подвох в том, что этот же запрос отлично работает на моей локальной машине и также работает на моем предыдущем хосте. Кстати, это из зрелого проекта - phpdevshell - так что я думаю, что эти парни знают, что делают, хотя вы никогда не знаете.
Любая подсказка приветствуется.
Я использую phpMyAdmin.
13 ответов
Как говорит @Devart, общая длина вашего индекса слишком велика.
Короткий ответ заключается в том, что вам не следует индексировать такие длинные столбцы VARCHAR, так как индекс будет очень громоздким и неэффективным.
Рекомендуется использовать префиксные индексы, чтобы индексировать только левую подстроку данных. Большинство ваших данных в любом случае будет намного короче, чем 255 символов.
Вы можете объявить длину префикса для каждого столбца при определении индекса. Например:
...
KEY `index` (`parent_menu_id`,`menu_link`(50),`plugin`(50),`alias`(50))
...
Но какова лучшая длина префикса для данного столбца? Вот метод, чтобы узнать:
SELECT
ROUND(SUM(LENGTH(`menu_link`)<10)*100/COUNT(`menu_link`),2) AS pct_length_10,
ROUND(SUM(LENGTH(`menu_link`)<20)*100/COUNT(`menu_link`),2) AS pct_length_20,
ROUND(SUM(LENGTH(`menu_link`)<50)*100/COUNT(`menu_link`),2) AS pct_length_50,
ROUND(SUM(LENGTH(`menu_link`)<100)*100/COUNT(`menu_link`),2) AS pct_length_100
FROM `pds_core_menu_items`;
Он сообщает вам долю строк, которые имеют не более заданной длины строки в menu_link
колонка. Вы могли бы видеть вывод как это:
+---------------+---------------+---------------+----------------+
| pct_length_10 | pct_length_20 | pct_length_50 | pct_length_100 |
+---------------+---------------+---------------+----------------+
| 21.78 | 80.20 | 100.00 | 100.00 |
+---------------+---------------+---------------+----------------+
Это говорит о том, что 80% ваших строк содержат менее 20 символов, а все ваши строки - менее 50 символов. Таким образом, нет необходимости индексировать больше, чем длина префикса 50, и, конечно, нет необходимости индексировать полную длину 255 символов.
PS: INT(1)
а также INT(32)
Типы данных указывает на другое недоразумение о MySQL. Числовой аргумент не влияет на хранение или диапазон значений, допустимых для столбца. INT
всегда 4 байта, и он всегда допускает значения от -2147483648 до 2147483647. Числовой аргумент - это заполнение значений во время отображения, которое не действует, если вы не используете ZEROFILL
вариант.
Эта ошибка означает, что длина индекса index
больше 1000 байтов. MySQL и механизмы хранения могут иметь это ограничение. У меня похожая ошибка на MySQL 5.5 - "Указанный ключ был слишком длинным; максимальная длина ключа составляет 3072 байта при запуске этого скрипта:
CREATE TABLE IF NOT EXISTS test_table1 (
column1 varchar(500) NOT NULL,
column2 varchar(500) NOT NULL,
column3 varchar(500) NOT NULL,
column4 varchar(500) NOT NULL,
column5 varchar(500) NOT NULL,
column6 varchar(500) NOT NULL,
KEY `index` (column1, column2, column3, column4, column5, column6)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
UTF8 является многобайтовым, и длина ключа вычисляется таким образом - 500 * 3 * 6 = 9000 байт.
Но обратите внимание, следующий запрос работает!
CREATE TABLE IF NOT EXISTS test_table1 (
column1 varchar(500) NOT NULL,
column2 varchar(500) NOT NULL,
column3 varchar(500) NOT NULL,
column4 varchar(500) NOT NULL,
column5 varchar(500) NOT NULL,
column6 varchar(500) NOT NULL,
KEY `index` (column1, column2, column3, column4, column5, column6)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
... поскольку я использовал CHARSET=latin1, в этом случае длина ключа составляет 500 * 6 = 3000 байт.
У меня была эта проблема, и я решил следующее:
причина
Существует известная ошибка в MySQL, связанная с MyISAM, набором символов UTF8 и индексами, которые вы можете проверить здесь.
разрешение
Убедитесь, что MySQL настроен с механизмом хранения InnoDB.
Измените механизм хранения, используемый по умолчанию, чтобы новые таблицы всегда создавались соответствующим образом:
set GLOBAL storage_engine='InnoDb';
Для MySQL 5.6 и более поздних версий используйте следующее:
SET GLOBAL default_storage_engine = 'InnoDB';
И, наконец, убедитесь, что вы следуете инструкциям, приведенным в разделе " Миграция на MySQL".
Запустите этот запрос перед созданием или изменением таблицы.
SET @@global.innodb_large_prefix = 1;
это установит максимальную длину ключа в 3072 байта
если вы используете Laravel 7 или Laravel 8, перейдите в config/database.php
'engine' => 'innoDb',
это должно работать, особенно с использованием Wamp или Xampp.
Я столкнулся с той же проблемой, использованной ниже запрос для ее решения.
При создании БД вы можете использовать кодировку utf-8
например. create database my_db character set utf8 collate utf8_bin;
Ну, я только что изменился с
MyISAM
к
InnoDB
как это
Перед изменением
ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
После изменения
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Этот предел размера индекса больше в 64-битных сборках MySQL.
Я нарушил это ограничение, пытаясь вывести нашу базу данных dev и загрузить ее на локальный виртуальный компьютер VMWare. Наконец, я понял, что удаленный сервер разработчика был 64-битным, и я создал 32-битный вирт. Я только что создал 64-битную виртуальную машину и смог загрузить базу данных локально.
Я только что обошел эту ошибку, просто изменив значения "длины" в исходной базе данных на общую сумму около 1000, изменив ее структуру, а затем экспортировав ее на сервер.:)
Получив такое же исключение при запуске внутреннего приложения, в этом случае мы можем установить движок «InnoDb» set GLOBAL storage_engine='InnoDb';
если приведенная выше конфигурация не работает для вас, измените длину ключа, например, если по умолчанию выбрано 255 символов, вы можете изменить ее ниже 100. Пример — создать роль таблицы ( role_name varchar (99) не null, role_description varchar(255) , первичный ключ (имя_роли)); это работает для меня
Если sql не создан самостоятельно, возможно, просто проверьте и установите длину столбца на обычную длину.
Я перепробовал так много трюков... но ни один из них мне не помог, а потом я нашел... самый лучший и простой.
if you are working with mysql-workbench,
while altering index select (Engine:)-innoDb.
apply and enjoy...
У меня была эта ошибка, и я изменил длину столбца таблицы меньше для индексированных столбцов внешнего ключа, поэтому я изменил ее следующим образом:
VARCHAR(1024)
К:
VARCHAR(512)
И снова запустите запрос.