UTF-8: Загальне? Бін? Unicode?


279

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

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

  1. Чи слід зберігати поданий користувачем вміст у колонках UTF-8 General або UTF-8 Unicode CI?
  2. До якого типу даних застосовано UTF-8 Binary?

16
Бічна примітка, але замість цього utf8, використовуйте utf8mb4замість неї повну підтримку UTF-8. Коментуючи тут, оскільки відповіді на це популярне питання цього не стосуються. mathiasbynens.be/notes/mysql-utf8mb4
Стівен Р. Луміс

Якщо ви хочете скласти корпус, але чутливість до акцентів, будь ласка, подайте запит на bugs.mysql.com .
Рік Джеймс

Або натисніть "Впливає на мене" на bugs.mysql.com/bug.php?id=58797 та додайте коментар.
Рік Джеймс

Відповіді:


299

Загалом, utf8_general_ci швидше, ніж utf8_unicode_ci , але менш правильне.

Ось різниця:

Для будь-якого набору символів Unicode операції, виконані за допомогою зіставлення _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 чутливий до регістру (серед інших відмінностей), оскільки порівнює двійкові значення символів.


2
Я думаю, що якщо у вас немає вагомих причин використовувати _unicode_ci, тоді використовуйте _general_ci.
Сагі

4
Це насправді не відповідає глибоко на це питання. Яка різниця між цими порівняннями саме?
Pekka

4
Ви праві, точна різниця тут не передбачена заради простоти. Я додав посилання на публікацію з точною різницею.
Сагі

Примітка show collation;дозволяє бачити порівняння за замовчуванням для кожного набору символів. 5.1 показано utf8_general_ciза замовчуванням для utf8.
Девід Карбоні

9
Чи є ресурси, які б поглиблювали фактичну різницю швидкостей між двома порівняннями? Ми говоримо про падіння продуктивності на 0,1% або зниження на 10%?
Емфрам Ставангер

90

Ви також повинні знати про те, що при utf8_general_ci при використанні поля varchar як унікального або первинного індексу, що вставляє 2 значення типу "a" і "á", дасть дублюючу помилку ключа.


3
Дякую, це корисно, щоб уникнути подібних імен користувачів (наприклад, якщо "jose" існує, я б не хотів, щоб хто-небудь інший створив користувача "josé"). Примітка: це також справедливо для більшості зіставлень utf8 (крім utf8_bin). Найбезпечніший / найбезпечніший / найповнішийutf8_unicode_ci
Коста,

2
Я використовую utf8_bin там, де хочу, щоб в індексі відрізнялися jose та josé. Наприклад, стовпець, який записує операції пошуку / заміни, де користувач, можливо, вирішив шукати josé та замінити його на jose. (Я пишу програму з електронних таблиць)
Buttle Butkus

33
  • utf8_binсліпо порівнює біти. Ніякого складання корпусу, ніякого викреслення акценту.
  • utf8_general_ciпорівнює один байт з одним байтом. Це дійсно складчастість і викреслення акценту, але жодне порівняння з двома символами: в цьому зіставленні ijне дорівнює ij.
  • utf8_*_ci- це набір мовних правил, але інакше подібне unicode_ci. Деякі особливі випадки: Ç, Č, ch,ll
  • utf8_unicode_ciдотримується старого стандарту Unicode для порівнянь. ij= ij, але ae! =æ
  • utf8_unicode_520_ciслід за новим стандартом Unicode. ae=æ

Детальну інформацію про те, що дорівнює рівним тим, що є у різних порівняннях utf8, див. У таблиці порівняння.

utf8, як визначено MySQL , обмежується 1-3-байтовими кодами utf8. Це залишає поза межами Емоджі та деяких китайців. Тож вам слід справді перейти до того, utf8mb4якщо ви хочете вийти за межі Європи.

Вищезазначені пункти стосуються utf8mb4, після відповідної зміни правопису. Ідучи вперед, utf8mb4і utf8mb4_unicode_520_ciвіддають перевагу.

  • utf16 і utf32 - варіанти на utf8; для них практично немає користі.
  • ucs2 ближче до "Unicode", ніж "utf8"; користі від цього практично немає.

1
Повторне "налаштування": 8,0 зібрань показує, як різні символи, дифтонги тощо порівнюють у порівнянні 8.0 utf8mb4; utf8 здебільшого те саме.
Рік Джеймс

І 8,0 зіставлення знаходяться на рівні значно швидшого, ніж 5.x.
Рік Джеймс

Було б добре, якби ця сторінка вгорі містила список utf8mb4_bin. Я знаю, що це зовсім не відповідає персонажам, але це добре для новачків.
Хенк Полі

6

Дійсно, я перевірив збереження значень типу "é" та "e" у стовпці з унікальним індексом, і вони викликають помилку дублювання як "utf8_unicode_ci", так і "utf8_general_ci". Ви можете зберегти їх лише у зібраному стовпчику 'utf8_bin'.

І документи mysql (у http://dev.mysql.com/doc/refman/5.7/uk/charset-applications.html ) пропонують у своїх прикладах встановити зіставлення 'utf8_general_ci'.

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

1
Я зробив швидкий тест на це, і, здається, це точно. Обидва зібрання поводяться однаково, коли мова йде про унікальний ключ на стовпчику та значення з тильдами тощо.
MirroredFate

@MirroredFate Гаразд, я повинен додати там, що стовпець повинен мати унікальний індекс для спричинення цієї помилки. Це випливає з моєї відповіді.
vitalii

3

Прийнята відповідь застаріла.

Якщо ви використовуєте 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


Ця відповідь (правильно) стосується питань кодування Emoji (та деяких китайців). Але питання, схоже, зосереджено на Collation. utf8mb4_unicode_ciтрактує (я думаю) всіх Емоджі як рівних. utf8mb4_unicode_520_ciдає наказ Емоджі.
Рік Джеймс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.