Laravel Ошибка синтаксиса или нарушение доступа: 1071 Указанный ключ был слишком длинным; максимальная длина ключа - 1000 байт [dубликат]

Вы можете использовать вложенные циклы.

  для моего $ e1 (qw (foo bar baz)) {для моего $ e2 (qw (cat dog)) {для моего $ e3 (qw  (1 2 3 4)) {my @choice = ($ e1, $ e2, $ e3);  ...}}}  

Когда вам нужно произвольное количество вложенных циклов, вы можете использовать Algorithm :: Loops 's NestedLoops ].

  использовать Алгоритм :: Петли qw (NestedLoops);  my @lists = ([qw (foo bar baz)], [qw (cat dog)], [qw (1 2 3 4)],);  my $ iter = NestedLoops (\ @ lists);  while (my @choice = $ iter- & gt; ()) {...}  

379
задан OMG Ponies 23 May 2011 в 22:32
поделиться

27 ответов

767 bytes - это ограничение префикса для таблиц 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), столбец 2 (200));   

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

293
ответ дан Paweł Gościcki 16 August 2018 в 00:44
поделиться
  • 1
    Чтобы применить, указав подмножество столбца, а не всю сумму. Хорошее решение. – Steven 29 November 2009 в 05:14
  • 2
    Это не объясняет, почему поля, значительно ниже предела длины, превышают ограничение длины ... – Cerin 8 November 2013 в 19:15
  • 3
    Я пробовал редактировать информацию, которую @Cerin отсутствует выше, что явно считается недостающим и для других, но она отвергается как более подходящая в качестве комментария. Для тех, кто пытается понять, почему 500 + 20 & gt; 767 см. Комментарий Штефана Эндрюллиса к ответу Жюльена. – Letharion 14 January 2015 в 09:19
  • 4
    Это может быть проблемой. Например: у меня есть имя поля (255) и добавление уникального в это поле по имени (191), когда я использую utf8mb4. Если у меня есть мой пользователь, добавьте свое имя с помощью «IJUE3ump5fiUuCi16jSofYS234MLschW4wsIktKiBrTPOTKBK6Vteh5pNuz1tKjy ... aO500mlJs», а другой пользователь добавит свое имя с помощью этого «IJUE3ump5fiUuCi16jSofYS234MLschW4wsIktKiBrTPOTKBK6Vteh5pNuz1tKjy ... aO500mlJa». Разный - последний символ. Он должен пройти проверку, не застревавшуюся при дублировании записи. – vee 30 July 2016 в 15:24
  • 5
    Предел индекса - 767 байт , а не символы. И поскольку набор символов Mysql utf8mb4 (который остальной мир вызывает utf8), требуется (не более) 4 байта на символ , вы можете индексировать только до VARCHAR ( 191) . Набор символов Mysql's utf8 (который весь мир нарушает) требует не более 3 байтов на символ, поэтому, если вы используете это (что вы не должны ), вы может индексироваться до VARCHAR (255) – Stijn de Witt 5 December 2016 в 11:17

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

  CREATE TABLE, ЕСЛИ НЕ СУЩЕСТВУЕТ your_table (id int (7) UNSIGNED NOT NULL AUTO_INCREMENT, имя 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, если не EXISTS your_table (id int (7) UNSIGNED NOT NULL AUTO_INCREMENT, имя varchar (256) COLLATE utf8mb4_bin  NOT NULL, PRIMARY KEY (id)) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 AUTO_INCREMENT = 1 ROW_FORMAT = FIXED;   

, но вам нужно проверить уникальность этого столбца из кода или добавить новый столбец в качестве MD5 или SHA1 столбца varchar

0
ответ дан 10undertiber 16 August 2018 в 00:44
поделиться
  • 1
    Тогда ваш уникальный ключ потерян. Я думаю, что лучший способ - просто уменьшить длину имени до 191. – haudoing 3 February 2015 в 03:44
  • 2
    Зачем проверять уникальность программно, если это встроенная функция БД? – Paul Tomkiel 27 May 2015 в 07:24

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

   ALTER TABLE `mytable` ADD UNIQUE (` column1` (200), `column2` (200));   
-1
ответ дан Abdul 16 August 2018 в 00:44
поделиться

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

Для Workbench MySQL 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 \» «cd Program Files \ MySQL \ MySQL Server 5.7 \ bin».
  3. Теперь выполнить команду mysql -u userName - p databasescheema Теперь он запросил пароль соответствующего пользователя. Предоставьте пароль и войдите в подсказку mysql.
  4. Мы должны установить некоторые глобальные настройки, чтобы ввести приведенные ниже команды по одному набору глобальных innodb_large_prefix = on; установить глобальный innodb_file_format = barracuda; set global innodb_file_per_table = true;
  5. Теперь, в конце, мы должны изменить ROW_FORMAT требуемой таблицы по умолчанию своим COMPACT, мы должны установить его в DYNAMIC.
  6. использовать следующую команду alter table table_name ROW_FORMAT = DYNAMIC;
  7. Выполнено
5
ответ дан Adrian Cid Almaguer 16 August 2018 в 00:44
поделиться
  • 1
    Я не могу найти это: 6. установите значение параметра innodb_default_row_format значение DYNAMIC. – Adrian Cid Almaguer 24 January 2017 в 15:45
  • 2
    если я использую set global innodb_default_row_format = DYNAMIC; Я вижу это сообщение: ERROR 1193 (HY000): Неизвестная системная переменная 'innodb_default_row_format' – Adrian Cid Almaguer 24 January 2017 в 15:58
  • 3
    как вы получили ошибку от workbench до cmd? Я сделал это с рабочего места, у него есть опция напрямую. – Abhishek 24 January 2017 в 16:01
  • 4
    Я делаю это из CMD, потому что не вижу опции в Workbench – Adrian Cid Almaguer 24 January 2017 в 16:08
  • 5
    Я вижу проблему, которую этот var был представлен в версии v.5.7.9, и у меня версия v5.6.33, спасибо – Adrian Cid Almaguer 24 January 2017 в 16:18

Когда вы достигнете предела. Задайте следующее:

  • INNODB utf8 VARCHAR (255)
  • INNODB utf8mb4 VARCHAR (191)
198
ответ дан Aley 16 August 2018 в 00:44
поделиться
  • 1
    Это лучший ответ. Простой, прямо к точке, а также включает ограничение utf8mb4 (которое является наиболее часто используемым кодированием для новых баз данных, поскольку оно принимает emojis / etc). – Claudio Holanda 8 September 2016 в 00:48
  • 2
    потому что 767/4 ~ = 191 и 767/3 ~ = 255 – Accountant م 8 November 2017 в 10:13
  • 3
    где и как его установить? – Dinesh Sunny 20 May 2018 в 07:14
  • 4
    Да, указав ENGINE = InnoDB DEFAULT CHARSET = utf8 в конце инструкции CREATE TABLE , я смог получить первичный файл VARCHAR (255) ключ. Благодарю. – xonya 10 June 2018 в 14:07
  • 5
    кто-то дал ему +1 превысить предел 191 :) – CagCak 8 July 2018 в 11:15

Решение для Laravel Framework

Согласно Laravel 5.4. * documentation ; Вы должны установить длину строки по умолчанию в методе

boot

для

app / Providers / AppServiceProvider. php

файл следующим образом:

  использовать Illuminate \ Support \ Facades \ Schema;  public function boot () {Schema :: defaultStringLength (191);  }  

Объяснение этого исправления, данное Laravel 5.4. * documentation ;

Laravel использует набор символов utf8mb4 по умолчанию , который включает поддержку для хранения «emojis» в базе данных. Если вы используете версию MySQL старше версии 5.7.7 или MariaDB старше версии 10.2.2, вам может потребоваться вручную настроить длину строки по умолчанию, сгенерированную миграциями, чтобы MySQL создавал для них индексы. Вы можете настроить это, вызывая метод Schema :: defaultStringLength в вашем AppServiceProvider

. Кроме того, вы можете включить параметр innodb_large_prefix для вашей базы данных. Обратитесь к документации вашей базы данных, чтобы узнать, как правильно включить эту опцию.

22
ответ дан alishaukat 16 August 2018 в 00:44
поделиться
  • 1
    кто сказал что-нибудь о php, это вопрос db – Bojan Petkovic 15 November 2017 в 19:42
  • 2
    @BojanPetkovic хорошо, я только что пришел из вопроса Laravel, и этот ответ на самом деле решил мою проблему. – mkmnstr 16 November 2017 в 01:56
  • 3
    это удачный ответ. Я бы потратил впустую часы, если это не здесь. – Code Tree 19 March 2018 в 04:41
  • 4
    Документация @Bobby Laravel дает свое объяснение в заголовке «Index Lengths & amp; MySQL / MariaDB & quot; [D0] laravel.com/docs/5.4/migrations#creating-indexes – alishaukat 11 April 2018 в 14:50
  • 5
    @Bobby Я обновил ответ. Я добавил объяснение, данное документацией laravel для этого исправления. – alishaukat 11 April 2018 в 15:08

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

36
ответ дан Amber 16 August 2018 в 00:44
поделиться
  • 1
    Если это UTF8, символ может использовать до 4 байтов, так что столбец с 20 символами равен 20 * 4 + 1 байт, а столбец 500 символов - 500 * 4 + 2 байтов – Thanatos 29 November 2009 в 04:46
  • 2
    Для чего это стоит, у меня была такая же проблема, и переключение с utf8_general_ci на utf8_unicode_ci решило проблему для меня. Я не знаю, почему хотя :( – Andresch Serj 17 July 2012 в 08:24
  • 3
    Для столбца VARCHAR (256) с индексом UNIQUE изменение сортировки не повлияло на меня, как это было для @Andresch. Однако уменьшение длины от 256 до 255 действительно позволило решить эту проблему. Я не понимаю, почему, поскольку 767 / max 4 байта на символ даст максимум 191? – Arjan 5 November 2012 в 16:45
  • 4
    255 * 3 = 765; 256 * 3 = 768 . Кажется, ваш сервер был asssuming 3 байта на символ, @Arjan – Amber 5 November 2012 в 18:11
  • 5
    @Greg: Вы правы, но это необходимо уточнить: сам UTF-8 использует 1-4 байта на кодовую точку. «Наборы символов MySQL» (действительно кодирование) имеет набор символов, называемый "utf8" который способен кодировать некоторые UTF-8 и использует 1-3 байта на кодовую точку и не способен кодировать кодовые точки вне BMP. Он также включает в себя еще один набор символов, называемый «utf8mb4», который использует 1-4 байта на кодовую точку и способен кодировать все кодовые точки Unicode. (utf8mb4 - UTF-8, utf8 - странная версия UTF-8.) – Thanatos 8 May 2013 в 23:54

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

  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 И s.COLUMN_NAME = c.COLUMN_NAME WHERE c.TABLE_SCHEMA = DATABASE () И c.  CHARACTER_MAXIMUM_LENGTH & gt;  191 И c.DATA_TYPE IN ('char', 'varchar', 'text')  
1
ответ дан Andrew 16 August 2018 в 00:44
поделиться

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

0
ответ дан AnkitK 16 August 2018 в 00:44
поделиться
  Указанный ключ слишком длинный;  max длина ключа составляет 767 байт  

Это сообщение вы получили, потому что 1 байт равен 1 символу, только если вы используете набор символов latin-1 . Если вы используете utf8 , каждый символ будет считаться 3 байтами при определении вашего столбца ключа. Если вы используете utf8mb4 , каждый символ будет считаться 4 байтами при определении вашего столбца ключа. Таким образом, вам нужно умножить предел символов вашего ключевого поля на, 1, 3 или 4 (в моем примере), чтобы определить количество байт, которые ключевое поле пытается разрешить. Если вы используете uft8mb4, вы можете определить только 191 символ для собственного поля InnoDB, primary key. Просто не нарушайте 767 байт.

17
ответ дан Anthony Rutledge 16 August 2018 в 00:44
поделиться

Я думаю, что 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, чтобы ускорить поиск.
21
ответ дан Buksy 16 August 2018 в 00:44
поделиться
  • 1
    Это сделал трюк. У меня был varchar (256), и мне пришлось изменить его на varchar (250). – MaRmAR 9 March 2017 в 09:35

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

Резервное копирование (без> перенаправления)

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

Восстановить (без & lt; redirect)

  # mysql -u root -p --default-character-set = utf8 databasename mysql & gt;  Имена SET «utf8» mysql & gt;  SOURCE bkp.sql  

Ошибка «Указанный ключ был слишком длинным, максимальная длина ключа - 767 байт» исчезла.

0
ответ дан Cassio Seffrin 16 August 2018 в 00:44
поделиться

Вот мой оригинальный ответ:

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

drop database, если существует 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

7
ответ дан Châu Hồng Lĩnh 16 August 2018 в 00:44
поделиться

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

  'charset' =  & GT;  'utf8mb4', 'collation' = & gt;  'utf8mb4_unicode_ci',  

 to

  'charset' = & gt;  'utf8', 'collation' = & gt;  'utf8_unicode_ci',  
-2
ответ дан despotbg 16 August 2018 в 00:44
поделиться
  • 1
    В настоящее время utf8mb4 должен быть кодировкой по умолчанию. В противном случае вы не будете поддерживать более новые символы. – Arany 10 July 2018 в 11:03
  • 2
    Вы не будете поддерживать emojis, когда вы переключаетесь с utf8 из utf8mb4 . – Player1 16 July 2018 в 19:42

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

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

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

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

  column1 varchar (20) utf8_general_ci column2 varchar (500) utf8_general_ci  
2
ответ дан Devy 16 August 2018 в 00:44
поделиться

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

15
ответ дан diyism 16 August 2018 в 00:44
поделиться
  • 1
    Обратите внимание, что это не позволит вам выполнять сканирование диапазонов по этим столбцам. Длина префикса на VARCHAR позволит вам сохранить эту черту, вызывая, возможно, ложные совпадения в индексе (и сканирование и поиск строк для их устранения) (см. Принятый ответ). (Это, по сути, ручной хэш-индекс, который, к сожалению, MysQL не поддерживает таблицы InnoDB.) – Thanatos 8 May 2013 в 23:58

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

  SET @@ global.innodb_large_prefix = 1;   

это увеличит предел до 3072 байта .

33
ответ дан Fábio Batista 16 August 2018 в 00:44
поделиться
  • 1
    Есть ли недостаток в изменении на innodb_large_prefix во всем мире? И это то, что DB & quot; global & quot; или все БД ПОЛНОСТЬЮ ГЛОБАЛЬНЫ? – SciPhi 5 June 2014 в 23:02
  • 2
    Применяется только при использовании нестандартных форматов строк. См. [D0] dev.mysql.com/doc/refman/5.5/en/… . В частности, «Включить эту опцию, чтобы разрешить префиксы ключевых слов длиной более 767 байт (до 3072 байт) для таблиц InnoDB, которые используют форматы строк DYNAMIC и COMPRESSED». Формат строки по умолчанию не изменяется. – Chris Lear 15 July 2014 в 12:19
  • 3
    Это сработало для меня - более подробную информацию и руководство можно найти здесь: mechanics.flite.com/blog/2014/07/29/… – cwd 24 February 2015 в 03:59
  • 4
    Один задается вопросом об ударе по индексированию и поиску, если ключевое поле слишком велико. – Anthony Rutledge 7 August 2016 в 11:27
  • 5
    нам нужно перезапустить сервер mysql после этого? – SimpleGuy 19 January 2018 в 15:04

Я исправил эту проблему с помощью:

  varchar (200)  

заменен на

  varchar (191)   

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

1
ответ дан flik 16 August 2018 в 00:44
поделиться

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

Обратитесь к этой ссылке .

  1. Откройте клиент MySQL (или клиент MariaDB ).
  2. Он спросит ваш пароль, введите правильный пароль.
  3. Выберите свою базу данных, используя эту команду , используя my_database_name; [ ! d6]

База данных изменена

  1. set global innodb_large_prefix = on;

Query OK, 0 строк (0.00 sec)

  1. set global innodb_file_format = Barracuda;

Query OK, 0 строк, затронутых (0.02 сек.)

  1. Перейдите в свою базу данных на phpMyAdmin или что-то вроде этого для удобства управления. > Выберите базу данных> Просмотреть структуру таблицы> Перейдите на вкладку «Операции». > Измените ROW_FORMAT на DYNAMIC и сохраните изменения.
  2. Перейдите на вкладку структуры таблицы> Нажмите кнопку «Уникальная».
  3. Готово. Теперь у него не должно быть ошибок.

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

12
ответ дан huan son 16 August 2018 в 00:44
поделиться
  • 1
    если вы все еще ошибаетесь после ввода запроса выше, попробуйте перейти к & quot; phpmyadmin & quot; & GT; установить "сортировку" к вашим предпочтениям (для меня я использую «utf8_general_ci») & gt; клик применим (даже если его уже utf8) – Anthony Kal 25 May 2017 в 13:41

Для laravel 5.6

Шаги к следующему

  1. Перейти к app \ Providers \ AppServiceProvider.php
  2. Добавить это в провайдер || (Дон 't include pipe) использовать Illuminate \ Support \ Facades \ Schema;
  3. Внутри функции загрузки Добавить это || (Не включать конвейер) Schema :: defaultStringLength (191);

, что все, Наслаждайтесь.

0
ответ дан Iraniya Naynesh 16 August 2018 в 00:44
поделиться

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

0
ответ дан MajidJafari 16 August 2018 в 00:44
поделиться

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

11
ответ дан maknz 16 August 2018 в 00:44
поделиться

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

Итак, если вы используете «utf8», ваш первый столбец займет 60 байт index, а второй - 1500.

143
ответ дан morganwahl 16 August 2018 в 00:44
поделиться
  • 1
    - Вероятно, это означает, что при использовании utf8mb4 мне нужно установить их (не более) 191 как 191 * 4 = 764 & lt; 767. – Isaac 25 February 2016 в 15:25
  • 2
    @ Исаак Да, точно, – morganwahl 26 February 2016 в 17:32
  • 3
    Я думаю, что это может быть правильным ответом, но не могли бы вы уточнить, что нужно сделать, чтобы исправить такую ​​проблему? По крайней мере, для MySQL noobs, таких как я? – Adam Grant 3 June 2016 в 00:09
  • 4
    Нет никакого способа обойти этот предел индекса. Здесь речь идет об уникальных ограничениях; для них вы можете иметь один столбец с неограниченной длиной текста и другой, где вы храните хеш (например, MD5) этого текста, и используйте столбец хеша для вашего уникального ограничения. Вы должны будете убедиться, что ваша программа сохраняет хеши в актуальном состоянии, когда она изменяет текст, но есть различные способы справиться с этим без особых проблем. Честно говоря, MySQL должен реализовать такую ​​вещь, так что вам не нужно; Я не удивлюсь, если у MariaDB есть что-то вроде этого встроенного. – morganwahl 4 June 2016 в 22:51
  • 5
    Уникальный индекс на очень длинном столбце varchar встречается редко. Подумайте, зачем вам это нужно, потому что это может быть проблема дизайна. Если вам нужен только индекс для поиска, рассмотрите поле «ключевые слова», которое помещается в пределах 191 символа, или разделите текст на краткое описание и длинный / полный текст и т. Д. Если вам действительно нужен полнотекстовый поиск, рассмотрите использование специализированного программного обеспечения для это, например, Apache Lucene. – Stijn de Witt 5 December 2016 в 11:34

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

5
ответ дан Nids Barthwal 16 August 2018 в 00:44
поделиться

Если у кого-то возникают проблемы с INNODB / Utf-8, пытаясь поместить индекс UNIQUE в поле VARCHAR (256) , переключите его на VARCHAR ( 255) . Кажется, 255 является ограничением.

352
ответ дан PinkTurtle 16 August 2018 в 00:44
поделиться
  • 1
    Количество разрешенных символов зависит только от вашего набора символов. UTF8 может использовать до 3 байтов на символ, utf8mb4 до 4 байтов и latin1 всего 1 байт. Таким образом, для utf8 длина вашего ключа ограничена 255 символами, так как 3 * 255 = 765 & lt; 767 . – Stefan Endrullis 23 July 2014 в 09:25
  • 2
    Это смутило меня от разочарования - спасибо. Это должен быть принятый ответ IMO, учитывая, что пользователь использует InnoDB, утверждая, что они достигли ограничения 767b. – TheCarver 10 October 2015 в 16:05
  • 3
    AS Stefan Endrullis заявил, что это зависит от кодировки. Если вы используете UTF8, который использует 3 байта: 255x3 = 765, что ниже предела 767, а 256x3 = 768, что выше. Но если вы используете UTF8mb4 свой 255 * 4 = 1020, значит, это не реальное решение – bernhardh 2 June 2016 в 09:22
  • 4
    Этот ответ правильный. Однако , если 255 действительно работает для вас, это означает, что вы используете Mysql utf8 , который, к сожалению, сломан. Он может кодировать символы только в базовой многоязычной плоскости. Вы получите проблемы с персонажами, которые выходят за рамки этого. Например, те персонажи из Эможи, которые они добавляли, выходят за его пределы, я думаю. Поэтому вместо переключения на VARCHAR (255) , переключитесь на VARCHAR (191) и , переведите кодировку в utf8mb4 (на самом деле это просто utf8, но MySql хотел удержать. compat). – Stijn de Witt 5 December 2016 в 11:28
  • 5
    Не полезно для моего многоколоночного уникального ограничения. Это также не сработало бы для уникального ограничения многоколоночного OP. (даст общий размер 825 байт) – Barett 2 March 2017 в 17:53

Измените CHARSET в поле индекса жалобы на «latin1», то есть ALTER TABLE tbl CHANGE myfield myfield varchar (600) CHARACTER SET latin1 DEFAULT NULL; latin1 принимает один байт за один символ вместо четырех

0
ответ дан Stan Holodnak 16 August 2018 в 00:44
поделиться
  • 1
    И что, если он попытается вставить символы non-latin1 ? – Paul Tomkiel 27 May 2015 в 07:26
  • 2
    Это самое худшее. Никогда не делай этого. – Sebas 11 August 2015 в 02:33
  • 3
    в моем случае это на столбце, в котором хранятся имена путей с шестнадцатеричными символами ... так что это может быть решением для кого-то. это действительно зависит от того, что вы хотите сохранить ... – codewandler 16 September 2016 в 17:37
  • 4
    Я должен был уменьшить это, поскольку использование latin1 не является решением в 2016 году. У меня все еще есть ужасные кошмары о времени, когда нам пришлось конвертировать базу данных с latin1 в utf8 еще в 2007 году. Не красиво. Вообще. – Bet Lamed 13 October 2016 в 10:39
  • 5
    У меня была та же проблема с уникальным индексом в двух столбцах, где хранятся адреса биткойнов и идентификаторы транзакций. Они всегда будут символами ASCII, поэтому я буду использовать latin1 в этих столбцах. Upvoting. – alexg 26 December 2016 в 18:26

Убедитесь, что sql_mode подобен

  sql_mode = NO_ENGINE_SUBSTITUTION, STRICT_TRANS_TABLES  

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

  sql_mode = NO_ENGINE_SUBSTITUTION  

OR

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

   innodb_large_prefix = on  
1
ответ дан YakovL 16 August 2018 в 00:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: