UTF-8: Общие? Бин? Юникод?

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

Насколько я понимаю, я должен использовать UTF-8 General CI (без учета регистра) вместо двоичного UTF-8. Однако я не могу найти четкого различия между UTF-8 General CI и UTF-8 Unicode CI.

  1. Должен ли я хранить отправленный пользователем контент в столбцах UTF-8 General или UTF-8 Unicode CI?
  2. К какому типу данных применим UTF-8 Binary?

person Dolph    schedule 26.02.2010    source источник
comment
Боковое примечание, но вместо utf8 используйте utf8mb4 для полной поддержки UTF-8. Комментирую здесь, потому что ответы на этот популярный вопрос не касаются этого. mathiasbynens.be/notes/mysql-utf8mb4   -  person Steven R. Loomis    schedule 06.01.2016
comment
Если вы хотите сворачивать регистр, но при этом учитывать акцент, отправьте запрос на странице bugs.mysql.com.   -  person Rick James    schedule 15.03.2017
comment
Или щелкните «Затрагивает меня» на странице bugs.mysql.com/bug.php?id=58797 и добавьте комментарий.   -  person Rick James    schedule 06.06.2017


Ответы (5)


В целом utf8_general_ci быстрее, чем utf8_unicode_ci, но менее корректно.

Вот разница:

Для любого набора символов Юникода операции, выполняемые с использованием сопоставления _general_ci, быстрее, чем операции для сопоставления _unicode_ci. Например, сравнения для сортировки utf8_general_ci быстрее, но немного менее корректны, чем сравнения для utf8_unicode_ci. Причина этого в том, что utf8_unicode_ci поддерживает сопоставления, такие как расширения; то есть, когда один символ сравнивается как равный с комбинациями других символов. Например, в немецком и некоторых других языках «ß» равно «ss». utf8_unicode_ci также поддерживает сокращения и игнорируемые символы. utf8_general_ci - это устаревшее сопоставление, которое не поддерживает расширения, сокращения или игнорируемые символы. Он может производить только однозначное сравнение между персонажами.

Цитируется по: http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

Для более подробного объяснения, пожалуйста, прочтите следующее сообщение на форумах MySQL: http://forums.mysql.com/read.php?103,187048,188748

Что касается utf8_bin: и utf8_general_ci, и utf8_unicode_ci выполняют сравнение без учета регистра. Напротив, utf8_bin чувствителен к регистру (помимо других различий), потому что он сравнивает двоичные значения символов.

person Sagi    schedule 26.02.2010
comment
Я думаю, что если у вас нет веской причины использовать _unicode_ci, используйте _general_ci. - person Sagi; 26.02.2010
comment
Однако это не дает подробного ответа на вопрос. В чем именно разница между этими сопоставлениями? - person Pekka; 03.04.2011
comment
Вы правы, здесь для простоты не приводится точная разница. Я добавил ссылку на сообщение с точной разницей. - person Sagi; 16.09.2011
comment
NB show collation; позволяет вам видеть параметры сортировки по умолчанию для каждого набора символов. 5.1 показывает utf8_general_ci по умолчанию для utf8. - person David Carboni; 16.07.2012
comment
Есть ли какие-либо ресурсы, которые позволили бы более подробно изучить фактическую разницу в скорости между двумя сопоставлениями? Мы говорим о падении производительности на 0,1% или на 10%? - person Emphram Stavanger; 04.03.2013
comment
Означает ли сортировка utf8-bin точное двоичное совпадение? - person Calmarius; 11.03.2014

Вы также должны знать тот факт, что с utf8_general_ci при использовании поля varchar в качестве уникального или первичного индекса вставка двух значений, таких как 'a' и 'á', приведет к ошибке дублирования ключа.

person Alex Hepp    schedule 19.01.2011
comment
Спасибо, это полезно, чтобы избежать похожих имен пользователей (например, если jose существует, я бы не хотел, чтобы кто-то другой создал пользователя josé). NB: это также верно для большинства сопоставлений utf8 (кроме utf8_bin). Самый надежный / безопасный / полный - utf8_unicode_ci - person Costa; 10.04.2013
comment
Я использую utf8_bin там, где хочу, чтобы хосе и хосе выделялись в индексе. Например, столбец, в котором записываются операции поиска / замены, в которых пользователь мог решить найти josé и заменить его на jose. (Я пишу программу для работы с электронными таблицами) - person Buttle Butkus; 09.05.2013

  • utf8_bin слепо сравнивает биты. Не складывается корпус, не снимаются акценты.
  • utf8_general_ci сравнивает одну кодовую точку с одной кодовой точкой. Выполняется сворачивание регистра и удаление акцента, но без сравнения двух символов; например: ij не равно ij в этом сопоставлении.
  • utf8_*_ci - это набор правил для конкретного языка, но в остальном похож на unicode_ci. Некоторые особые случаи: Ç, Č, ch, ll
  • utf8_unicode_ci следует старому стандарту Unicode для сравнений. _12 _ = _ 13_, но ae! = æ
  • utf8_unicode_520_ci следует новому стандарту Unicode. ae = æ

См. диаграмму сопоставления для получения подробной информации о том, что равно чему в различных сопоставлениях utf8.

utf8, в соответствии с определением MySQL ограничен 1–3-байтовыми кодами utf8. Это не учитывает Emoji и некоторые из китайских. Так что вам действительно стоит перейти на utf8mb4, если вы хотите выйти далеко за пределы Европы.

Вышеуказанные пункты относятся к utf8mb4 после соответствующего изменения написания. В дальнейшем предпочтительнее использовать utf8mb4 и utf8mb4_unicode_520_ci.

  • utf16 и utf32 - варианты на utf8; они практически бесполезны.
  • ucs2 ближе к Unicode, чем utf8; от него практически нет никакой пользы.
person Rick James    schedule 29.07.2016
comment
Следите за обновлениями: сопоставления 8.0 показывает, как различные символы, дифтонги, и т.д., сравните в сопоставлении 8.0 utf8mb4; utf8 в основном то же самое. - person Rick James; 16.02.2017
comment
И сопоставления 8.0 значительно быстрее, чем 5.x. - person Rick James; 06.06.2017
comment
было бы неплохо, если бы на этой странице вверху был указан utf8mb4_bin. Я знаю, что он вообще не выполняет сопоставление символов, но это хорошо для новичков. - person Henk Poley; 19.07.2019
comment
@TobySpeight - Спасибо. Теперь меня беспокоит, что я напортачил с другими ответами; Я говорил такие вещи много раз за последнее десятилетие. Теперь, когда 8.0 является текущей версией, многие подобные вопросы не задаются - general_ci больше не используется по умолчанию. - person Rick James; 01.04.2021

Принятый ответ устарел.

Если вы используете MySQL 5.5.3+, используйте utf8mb4_unicode_ci вместо utf8_unicode_ci, чтобы символы, вводимые вашими пользователями, не вызывали ошибок.

utf8mb4 поддерживает, например, смайлы, а utf8 может выдать сотни ошибок, связанных с кодированием, например:

Incorrect string value: ‘\xF0\x9F\x98\x81…’ for column ‘data’ at row 1

person Marwann    schedule 10.12.2018
comment
Этот ответ (правильно) решает проблемы с кодировкой эмодзи (и некоторых из них). Но вопрос, похоже, сосредоточен на сопоставлении. utf8mb4_unicode_ci рассматривает (я думаю) все Emoji как равные. utf8mb4_unicode_520_ci отдает приказ Emoji. - person Rick James; 19.07.2019

На самом деле, я тестировал сохранение таких значений, как «é» и «e» в столбце с индексом уникальный, и они вызывают повторяющуюся ошибку как для «utf8_unicode_ci», так и «utf8_general_ci». Вы можете сохранить их только в сопоставленном столбце utf8_bin.

И документы mysql (в http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html) предлагает в своих примерах установить параметры сортировки utf8_general_ci.

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
person vitalii    schedule 08.07.2014
comment
Я провел быстрый тест, и он оказался точным. Оба сопоставления ведут себя одинаково, когда речь идет об уникальном ключе в столбце, значениях с тильдами и т.п. - person MirroredFate; 30.06.2015
comment
@MirroredFate Хорошо, я должен добавить туда этот столбец, который должен иметь уникальный индекс, вызывающий эту ошибку. Это подразумевается в моем ответе. - person vitalii; 01.07.2015