Когда использовать utf-8 и когда использовать latin1 в MySQL?

Я знаю, что MySQL по умолчанию имеет кодировку latin1, и, по-видимому, требуется 1 байт для хранения символа в latin1 и 3 байта для хранения символа в utf-8 — это правильно?

Я работаю над сайтом, который, я надеюсь, будет использоваться во всем мире. Мне абсолютно необходимо иметь utf-8? Или я смогу обойтись без использования latin1?

Кроме того, я попытался изменить некоторые таблицы с latin1 на utf8, но получил следующую ошибку: Speficief key was too long; max key length is 1000 bytes Кто-нибудь знает решение этой проблемы? И я должен действительно решить это или может быть достаточно latin1?

Спасибо, Алекс


person Genadinik    schedule 01.02.2011    source источник


Ответы (8)


для хранения символа в latin1 требуется 1 байт, а для хранения символа в utf-8 - 3 байта - это правильно?

Требуется 1 байт для хранения latin1 символа и от 1 до 3 байт для хранения UTF8 символа.

Если вы используете в своих строках только основные латинские символы и знаки препинания (от 0 до 128 в Unicode), оба набора символов будут занимать одинаковую длину.

Кроме того, я попытался изменить некоторые таблицы с latin1 на utf8, но получил эту ошибку: «Слишком длинный специальный ключ; максимальная длина ключа составляет 1000 байт». Кто-нибудь знает решение этой проблемы? И я должен действительно решить это или может быть достаточно latin1?

Если у вас есть столбец размером VARCHAR(334) или длиннее, MyISAM не позволит вам создать для него индекс, поскольку столбец может занять более 1000 байт.

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

person Quassnoi    schedule 01.02.2011
comment
Предполагая, что теперь нам нужно проиндексировать весь столбец, какой лучший обходной путь для индексации столбца, размер которого превышает 1000 байт? - person Pacerier; 11.07.2012
comment
@Pacerier: используйте индекс с префиксом: CREATE INDEX ix_mytable_longcolumn ON mytable (longcolumn(200)) - person Quassnoi; 11.07.2012
comment
Но это не индексирует весь столбец. Например, если нам нужен уникальный столбец размером более 1 КБ, мы можем использовать индекс с префиксом для первых 200 байт. Однако этот индекс с префиксом заставляет первые 200 байт быть уникальными. Я хочу, чтобы первые 200 байтов не были уникальными, первые 200 байтов могут быть равны, если все 1000 байтов уникальны в таблице. Какое лучшее решение для уникального столбца размером более 1 КБ? - person Pacerier; 11.07.2012
comment
@Pacerier: вам нужен индекс для поиска или для уникальности? Если для последнего, просто проиндексируйте хэш строки MD5 (или любой другой достаточно уникальный хеш). - person Quassnoi; 11.07.2012
comment
Для уникальности. Поскольку данные составляют более 1000 байт (допустим, 30 КБ), произойдет коллизия хэшей, поскольку выход составляет всего 64 байта. Другими словами, я считаю хэш-решение нестандартным, поскольку мы рискуем ошибкой, при которой данные определяются как уникальные, даже если они еще не существуют в таблице. Есть ли лучшее альтернативное решение? - person Pacerier; 11.07.2012
comment
@Pacerier: с любой приличной хэш-функцией вероятность столкновения хэшей не зависит от размера данных, а только от размера хэша и количества записей. Для любых реальных данных, которые вы теоретически можете хранить в одной таблице, безопасно полагаться, скажем, на SHA-2. Альтернативного решения нет, MyISAM не может обеспечить уникальность более 1000 байт. - person Quassnoi; 11.07.2012
comment
Хотя очень маловероятно, что на практике вы действительно столкнетесь с коллизией, если это вызывает серьезную озабоченность, вы также можете создать составной отпечаток нескольких хэшей. Например, возьмите MD5, SHA-1 и CRC32 и соедините их. - person defines; 14.04.2013

Как минимум я бы предложил использовать UTF-8. Ваши данные будут совместимы с любой другой базой данных, существующей в настоящее время, поскольку более 90% из них имеют кодировку UTF-8.

Если вы выберете LATIN1/ISO-8859-1, вы рискуете, что данные не будут сохранены должным образом, потому что они не поддерживают международные символы... поэтому вы можете столкнуться с чем-то вроде левой части этого изображения:

введите здесь описание изображения

Если вы используете UTF-8, вам не нужно иметь дело с этими < сильные>головные боли.

Что касается вашей ошибки, похоже, вам нужно оптимизировать базу данных. Рассмотрим это: http://bugs.mysql.com/bug.php?id=4541#c284415

Было бы полезно, если бы вы указали особенности в схеме таблицы и столбце для этой проблемы.

person meder omuraliev    schedule 01.02.2011

Если вы разрешаете пользователям публиковать сообщения на их родных языках и если вы хотите, чтобы в них участвовали пользователи из всех стран, вы должны переключить по крайней мере таблицы, содержащие эти сообщения, на UTF-8 — Latin1 охватывает только символы ASCII и западноевропейские символы. То же самое верно, если вы собираетесь использовать несколько языков для своего пользовательского интерфейса. См. этот пост, чтобы узнать, как выполнить миграцию.

person weltraumpirat    schedule 01.02.2011

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

Что касается ошибки, у вас, вероятно, есть поле ключа или индекса с более чем 333 символами, максимально допустимым в MySQL с кодировкой UTF-8. См. этот отчет об ошибке.

person Knyphe    schedule 01.02.2011
comment
Эти 333 символа сбивают с толку. :) Многие поля могут содержать более 333 символов, верно? Это числовое поле, которое не может содержать более 333 символов? В чем именно проблема обычно? Спасибо! - person Genadinik; 01.02.2011
comment
@Genadinik: зачем тебе индексировать весь столбец? Для любой реальной строки достаточно первых 20 символов или около того, чтобы индекс оставался селективным. - person Quassnoi; 01.02.2011
comment
Вероятно, в настоящее время у вас есть поле индекса или ключа, определенное как VARCHAR(1000) или подобное. В принципе, у вас не должно быть индекса или ключа для такого большого поля, но при преобразовании в UTF-8 поле увеличивается с 1000 байтов до 3000 байтов. Как заявил Quassnoi, MyISAM не позволит вам создать индекс для столбца размером более 1000 байт. Вам нужно будет просмотреть определения вашей таблицы, чтобы узнать, какой это столбец. - person Knyphe; 01.02.2011
comment
Хорошо, это поднимает, возможно, глупый вопрос :) ... но некоторые столбцы должны содержать более 1000 символов. Например, биографию пользователя или описание события. Или эта ошибка только для индекса varchar (1000) (что, скорее всего, где-то опечатка)? - person Genadinik; 01.02.2011
comment
Чтобы ответить на мой собственный вопрос - да, я сделал ошибку, имея ключ varchar (1000) - изменение этого решило эту конкретную ошибку :) всем спасибо :) - person Genadinik; 01.02.2011

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

Итак, короткий ответ: просто используйте UTF-8 с самого начала, это избавит вас от проблем позже.

person Sebastian    schedule 01.02.2011

Поскольку максимальная длина ключа составляет 1000 БАЙТОВ, если вы используете utf8, это ограничит вас до 333 символов.

Однако MySQL отличается от Oracle для кодировки. В Oracle у вас не может быть другого набора символов для каждого столбца, тогда как в MySQL вы можете, поэтому, возможно, вы можете установить ключ на latin1, а другие столбцы на utf8.

Наконец, я считаю, что только несуществующая версия 6.0alpha (выброшенная, когда Sun купила MySQL) могла вместить символы Unicode помимо BMP (базовый многоязычный план). Таким образом, даже с UTF-8 у вас не будет всего полного набора символов Unicode. На практике это проблема только для редких китайских иероглифов, если это действительно важно для вас.

person Alain Pannetier    schedule 01.02.2011

Я не эксперт, но я всегда понимал, что UTF-8 на самом деле представляет собой набор кодировок шириной 4 байта, а не 3. И, насколько я понимаю, реализация utf8_unicode_ci в MySQL обрабатывает только набор кодировок шириной 3 байта...

Если вам нужна полная 4-байтовая кодировка символов UTF-8, вам необходимо использовать кодировку utf8mb4_unicode_ci для вашей базы данных/таблиц MySQL.

person Obewan    schedule 30.05.2017

Текущая лучшая практика - никогда не использовать набор символов MySQL utf8. Вместо этого используйте utf8mb4, что является правильной реализацией стандарта.

Подробнее см. Объяснение Адама Хупера. .

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

Ошибка Specified key was too long; max key length is 1000 bytes возникает, когда индекс содержит столбцы в utf8mb4, так как индекс может превышать это ограничение. Вам нужно будет сократить длину некоторых столбцов символов или сократить длину индекса в столбцах, используя этот синтаксис, чтобы убедиться, что он короче ограничения.

ALTER TABLE.. ADD INDEX `myIndex` ( column1(15), column2(200) );

person Brandon    schedule 04.02.2021