Ошибка MySQL: спецификация ключа без длины ключа

У меня есть таблица с первичным ключом, который имеет тип varchar(255). Некоторые случаи возникли, когда 255 символов недостаточно. Я попытался изменить поле на текст, но я получаю следующую ошибку:

BLOB/TEXT column 'message_id' used in key specification without a key length

Как я могу это исправить?

edit: я также должен указать, что эта таблица имеет составной первичный ключ с несколькими столбцами.

13 ответов


ошибка происходит потому, что MySQL может индексировать только первые N символов BLOB или . Таким образом, ошибка в основном происходит, когда есть тип поля/столбца TEXT или BLOB или те принадлежат TEXT или BLOB типы, такие как TINYBLOB, MEDIUMBLOB, LONGBLOB, TINYTEXT, MEDIUMTEXT и LONGTEXT что вы пытаетесь сделать первичный ключ или индекс. С полным BLOB или TEXT без значения длины MySQL не может гарантировать уникальность столбца, поскольку он имеет переменную и динамическую размер. Итак, при использовании BLOB или TEXT типы как индекс, значение N должно быть предоставлено, чтобы MySQL мог определить длину ключа. Однако MySQL не поддерживает ограничение длины ключа на TEXT или BLOB. TEXT(88) просто не будет работать.

ошибка также появится при попытке преобразовать столбец таблицы из non-TEXT и non-BLOB типа, такие как VARCHAR и ENUM на TEXT или BLOB тип, столбец уже определен как уникальные ограничения или индекс. Этот Команда Alter Table SQL завершится ошибкой.

решение проблемы состоит в том, чтобы удалить TEXT или BLOB столбец из ограничения index или unique или установите другое поле в качестве первичного ключа. Если вы не можете этого сделать, и хотите установить ограничение на TEXT или попробуйте использовать VARCHAR введите и поместите на него ограничение длины. По умолчанию VARCHAR ограничено максимум 255 символами, и его предел должен быть указан неявно в скобке сразу после его декларации, я.е VARCHAR(200) ограничит его только 200 символами.

иногда, даже если вы не используете TEXT или BLOB связанный тип в вашей таблице также может появиться ошибка 1170. Это происходит в ситуации, например, когда вы указать VARCHAR столбец в качестве первичного ключа, но неправильно установите его длину или размер символов. VARCHAR может принимать только до 256 символов, поэтому все, что угодно, например VARCHAR(512) заставит MySQL автоматически конвертировать VARCHAR(512) до SMALLTEXT тип данных, который впоследствии происходит сбой с ошибкой 1170 по длине ключа, если столбец используется в качестве первичного ключа или уникального Или не уникального индекса. Чтобы решить эту проблему, укажите в качестве размера для


вы должны определить, какая ведущая часть TEXT столбец, который вы хотите индексировать.

InnoDB имеет ограничение 768 байты на ключ индекса, и вы не сможете создать индекс дольше, чем это.

это будет работать нормально:

CREATE TABLE t_length (
      mydata TEXT NOT NULL,
      KEY ix_length_mydata (mydata(255)))
    ENGINE=InnoDB;

обратите внимание, что максимальное значение размера ключа зависит от кодировки столбца. Это 767 символы для однобайтовой кодировки, такой как LATIN1 и только 255 символы UTF8 (MySQL использует только BMP который требует самое большее 3 байта на символ)

Если вам нужна вся ваша колонка будет PRIMARY KEY, расчета SHA1 или MD5 хеш и использовать его как PRIMARY KEY.


вы можете указать длину ключа в запросе alter table, например:

alter table authors ADD UNIQUE(name_first(20), name_second(20));

MySQL запрещает индексирование полного значения BLOB, TEXT и длинной VARCHAR столбцы, потому что данные, которые они содержат, могут быть огромными, и неявно индекс БД будет большим, что означает отсутствие выгоды от индекса.

MySQL требует, чтобы вы определили первые n символов для индексирования, и трюк состоит в том, чтобы выбрать число N, которое достаточно долго, чтобы дать хорошую избирательность, но достаточно короткое, чтобы сэкономить место. Префикс должен быть достаточно длинным, чтобы сделать индекс почти таким же полезным, как если бы вы проиндексировал весь столбец.

прежде чем мы пойдем дальше, давайте определим некоторые важные термины. индекс селективности соотношение общее количество различных индексированных значений и общее количество строк. Вот один пример для тестовой таблицы:

+-----+-----------+
| id  | value     |
+-----+-----------+
| 1   | abc       |
| 2   | abd       |
| 3   | adg       |
+-----+-----------+

если индексировать только первый символ (N=1), то индексная таблица будет выглядеть следующим образом:

+---------------+-----------+
| indexedValue  | rows      |
+---------------+-----------+
| a             | 1,2,3     |
+---------------+-----------+

в этом случае избирательность индекса равна IS=1/3 = 0.33.

давайте теперь посмотрим, что произойдет, если мы увеличим количество индексированных символов до двух (N=2).

+---------------+-----------+
| indexedValue  | rows      |
+---------------+-----------+
| ab             | 1,2      |
| ad             | 3        |
+---------------+-----------+

в этом сценарии=2/3=0.66, что означает, что мы увеличили селективность индекса, но мы также увеличили размер индекса. Хитрость состоит в том, чтобы найти минимальное число N, которое приведет к максимальному селективность.

есть два подхода, которые вы можете сделать расчеты для таблицы базы данных. Я сделаю демонстрацию на это дамп базы данных.

предположим, мы хотим добавить столбец фамилия в таблице сотрудники к индексу, и мы хотим определить наименьшее число N что произведет самую лучшую селективность индекса.

сначала давайте определим наиболее частые фамилии:

select count(*) as cnt, last_name 
from employees 
group by employees.last_name 
order by cnt

+-----+-------------+
| cnt | last_name   |
+-----+-------------+
| 226 | Baba        |
| 223 | Coorg       |
| 223 | Gelosh      |
| 222 | Farris      |
| 222 | Sudbeck     |
| 221 | Adachi      |
| 220 | Osgood      |
| 218 | Neiman      |
| 218 | Mandell     |
| 218 | Masada      |
| 217 | Boudaillier |
| 217 | Wendorf     |
| 216 | Pettis      |
| 216 | Solares     |
| 216 | Mahnke      |
+-----+-------------+
15 rows in set (0.64 sec)

Как видите, фамилия Баба является наиболее частым. Теперь мы собираемся найти наиболее часто встречающиеся фамилия префиксы, начинающиеся с пятибуквенных префиксов.

+-----+--------+
| cnt | prefix |
+-----+--------+
| 794 | Schaa  |
| 758 | Mande  |
| 711 | Schwa  |
| 562 | Angel  |
| 561 | Gecse  |
| 555 | Delgr  |
| 550 | Berna  |
| 547 | Peter  |
| 543 | Cappe  |
| 539 | Stran  |
| 534 | Canna  |
| 485 | Georg  |
| 417 | Neima  |
| 398 | Petti  |
| 398 | Duclo  |
+-----+--------+
15 rows in set (0.55 sec)

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

вот результаты для N=9

select count(*) as cnt, left(last_name,9) as prefix 
from employees 
group by prefix 
order by cnt desc 
limit 0,15;

+-----+-----------+
| cnt | prefix    |
+-----+-----------+
| 336 | Schwartzb |
| 226 | Baba      |
| 223 | Coorg     |
| 223 | Gelosh    |
| 222 | Sudbeck   |
| 222 | Farris    |
| 221 | Adachi    |
| 220 | Osgood    |
| 218 | Mandell   |
| 218 | Neiman    |
| 218 | Masada    |
| 217 | Wendorf   |
| 217 | Boudailli |
| 216 | Cummings  |
| 216 | Pettis    |
+-----+-----------+

вот результаты для N=10.

+-----+------------+
| cnt | prefix     |
+-----+------------+
| 226 | Baba       |
| 223 | Coorg      |
| 223 | Gelosh     |
| 222 | Sudbeck    |
| 222 | Farris     |
| 221 | Adachi     |
| 220 | Osgood     |
| 218 | Mandell    |
| 218 | Neiman     |
| 218 | Masada     |
| 217 | Wendorf    |
| 217 | Boudaillie |
| 216 | Cummings   |
| 216 | Pettis     |
| 216 | Solares    |
+-----+------------+
15 rows in set (0.56 sec)

это очень хорошие результаты. Это означает, что мы можем сделать индекс в столбце last_name С индексирование только первых 10 символов. В столбце определения таблицы last_name определяется как VARCHAR(16), и это означает, что мы сохранили 6 байт (или больше, если в фамилии есть символы UTF8) на запись. В этой таблице есть 1637 различных значений, умноженных на 6 байт, это около 9 КБ, и представьте, как это число будет расти, если наша таблица содержит миллион строк.

вы можете прочитать другие способы вычисления числа N в моем посте индексы с префиксами в В MySQL.


alter table authors ADD UNIQUE(name_first(767), name_second(767));

Примечание : 767 - это ограничение количества символов, до которого MySQL будет индексировать столбцы при работе с Blob / text indexes

Ref:http://dev.mysql.com/doc/refman/5.7/en/innodb-restrictions.html


не имеют длинных значений в качестве первичного ключа. Это разрушит ваше представление. См. руководство mysql, раздел 13.6.13 "настройка производительности InnoDB и устранение неполадок".

вместо этого имейте суррогатный ключ int как первичный (с auto_increment), а ваш ключ loong как вторичный уникальный.


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


добавьте другой столбец varChar(255) (по умолчанию пустая строка не null), чтобы удерживать переполнение, когда 255 символов недостаточно, и измените этот PK для использования обоих столбцов. Однако это не похоже на хорошо разработанную схему базы данных, и я бы рекомендовал получить Data modeler, чтобы посмотреть, что у вас есть, с целью его рефакторинга для большей нормализации.


кроме того, если вы хотите использовать индекс в этом поле, вы должны использовать механизм хранения MyISAM и тип полнотекстового индекса.


решение проблемы заключается в том, что в CREATE TABLE заявление, вы можете добавить ограничение UNIQUE ( problemtextfield(300) ) после столбца создайте определения, чтобы указать key длина 300 символы TEXT поле, например. Тогда первый 300 символы problemtextfield TEXT поле должно быть уникальным, и любые различия после этого будут игнорироваться.


используйте вот так

@Id
@Column(name = "userEmailId", length=100)
private String userEmailId;

вы должны изменить тип столбца varchar или integer для индексации.


перейти к mysql edit table - > изменить тип столбца на varchar(45).