Мне интересно, есть ли «лучший» выбор для сортировки в MySQL для общего веб-сайта, где вы не уверены на 100%, что будет введено? Я понимаю, что все кодировки должны быть одинаковыми, например, MySQL, Apache, HTML и все, что находится внутри PHP.
В прошлом я устанавливал PHP для вывода в "UTF-8", но с каким сопоставлением это соответствует в MySQL? Я думаю , что это одна из UTF-8 из них, но я использовал utf8_unicode_ci
, utf8_general_ci
и utf8_bin
раньше.
Ответы:
Основным отличием является точность сортировки (при сравнении символов на языке) и производительность. Единственный специальный - это utf8_bin, который предназначен для сравнения символов в двоичном формате.
utf8_general_ci
несколько быстрее чемutf8_unicode_ci
, но менее точно (для сортировки). Конкретный язык utf8 кодирование (напримерutf8_swedish_ci
) содержит дополнительные правила языка , которые делают их наиболее точной для сортировки для этих языков. Большую часть времени я используюutf8_unicode_ci
(я предпочитаю точность небольшим улучшениям производительности), если у меня нет веских причин предпочитать конкретный язык.Вы можете прочитать больше о конкретных наборах символов Юникода в руководстве по MySQL - http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html
источник
utf8_unicode_*
utf8mb4
иutf8mb4_unicode_520_ci
. Они дают вам остальную часть китайского языка, а также улучшенную сортировку.На самом деле, вы, вероятно, хотите использовать
utf8_unicode_ci
илиutf8_general_ci
.utf8_general_ci
сортирует, удаляя все акценты и сортируя, как будто это ASCIIutf8_unicode_ci
использует порядок сортировки Unicode, поэтому он сортирует правильно на нескольких языкахОднако, если вы используете это только для хранения английского текста, они не должны отличаться.
источник
Будьте очень, очень осведомлены об этой проблеме, которая может возникнуть при использовании
utf8_general_ci
.MySQL не будет различать некоторые символы в операторах выбора, если используется
utf8_general_ci
сопоставление. Это может привести к очень неприятным ошибкам - особенно, например, когда задействованы имена пользователей. В зависимости от реализации, использующей таблицы базы данных, эта проблема может позволить злоумышленникам создать имя пользователя, соответствующее учетной записи администратора.Эта проблема раскрывается как минимум в ранних версиях 5.x - я не уверен, изменилось ли это поведение позже.
Я не администратор баз данных, но чтобы избежать этой проблемы, я всегда использую
utf8-bin
вместо регистронезависимого.Сценарий ниже описывает проблему на примере.
источник
'value'
и'valUe'
. Весь смысл сопоставления состоит в том, что он обеспечивает правила (среди прочего), когда две строки считаются равными друг другу.Лучше всего использовать набор символов
utf8mb4
с сопоставлениемutf8mb4_unicode_ci
.Набор символов,
utf8
поддерживает только небольшое количество кодовых точек UTF-8, около 6% возможных символов.utf8
поддерживает только базовую многоязычную плоскость (BMP). Там 16 других самолетов. Каждая плоскость содержит 65 536 символов.utf8mb4
поддерживает все 17 самолетов.MySQL будет обрезать 4-байтовые символы UTF-8, что приведет к повреждению данных.
Набор
utf8mb4
символов был введен в MySQL 5.5.3 2010-03-24.Некоторые из необходимых изменений для использования нового набора символов не являются тривиальными:
ROW_FORMAT=DYNAMIC
ПРИМЕЧАНИЕ. Для переключения
Barracuda
сAntelope
, возможно, потребуется перезапустить службу MySQL более одного раза.innodb_file_format_max
не изменится до тех пор , после того , как служба MySQL перезапущена для:innodb_file_format = barracuda
.MySQL использует старый
Antelope
формат файла InnoDB.Barracuda
поддерживает динамические форматы строк, которые вам понадобятся, если вы не хотите нажимать на ошибки SQL для создания индексов и ключей после переключения на кодировку:utf8mb4
Следующий сценарий был протестирован на MySQL 5.6.17: по умолчанию MySQL настроен так:
Остановите службу MySQL и добавьте параметры в существующий my.cnf:
Пример оператора SQL CREATE:
INDEX contact_idx (contact)
ifROW_FORMAT=DYNAMIC
, удаленную из оператора CREATE.ПРИМЕЧАНИЕ. Изменение индекса до первых 128 символов
contact
исключает необходимость использования Barracuda сROW_FORMAT=DYNAMIC
Также обратите внимание: когда говорится, что размер поля равен
VARCHAR(128)
128 байтам. Вы можете использовать 128, 4-байтовые символы или 128, 1-байтовые символы.Этот
INSERT
оператор должен содержать 4-байтовый символ 'poo' в строке 2:Вы можете увидеть количество места, используемого в
last
столбце:В вашем адаптере базы данных вы можете установить кодировку и параметры сортировки для вашего соединения:
В PHP это будет установлено для:
\PDO::MYSQL_ATTR_INIT_COMMAND
Ссылки:
источник
utf8mb4_unicode_520_ci
лучше. В будущем будетutf8mb4_unicode_800_ci
(или что-то в этом роде), поскольку MySQL будет соответствовать стандартам Unicode.Сопоставления влияют на то, как данные сортируются и как строки сравниваются друг с другом. Это означает, что вы должны использовать параметры сортировки, которые ожидают большинство ваших пользователей.
Пример из документации по кодировке Unicode :
Так что - это зависит от вашей ожидаемой пользовательской базы и от того, насколько вам нужна правильная сортировка. Для английской пользовательской базы
utf8_general_ci
должно хватить, для других языков, таких как шведский, были созданы специальные сопоставления.источник
По сути, это зависит от того, как вы думаете о строке.
Я всегда использую utf8_bin из-за проблемы, выделенной Гусом. На мой взгляд, что касается базы данных, строка по-прежнему просто строка. Строка - это число символов UTF-8. Символ имеет двоичное представление, так почему ему нужно знать язык, который вы используете? Обычно люди будут создавать базы данных для систем с многоязычными сайтами. В этом весь смысл использования UTF-8 в качестве набора символов. Я немного приверженец чистоты, но я думаю, что ошибка может сильно перевесить небольшое преимущество, которое вы можете получить при индексации. Любые языковые правила должны выполняться на гораздо более высоком уровне, чем СУБД.
В моих книгах «ценность» никогда не должна равняться миллиону лет.
Если я хочу сохранить текстовое поле и выполнить поиск без учета регистра, я буду использовать строковые функции MYSQL с функциями PHP, такими как LOWER () и функция php strtolower ().
источник
Для текстовой информации UTF-8, вы должны использовать,
utf8_general_ci
потому что ...utf8_bin
: сравнить строки по двоичному значению каждого символа в строкеutf8_general_ci
: сравнивать строки, используя общие правила языка и используя сравнения без учета регистраиначе это должно сделать поиск и индексацию данных более быстрым / более эффективным / более полезным.
источник
Принятый ответ довольно определенно предполагает использование utf8_unicode_ci, и хотя для новых проектов это здорово, я хотел бы рассказать о своем недавнем противоречивом опыте на тот случай, если он кого-нибудь сэкономит.
Поскольку utf8_general_ci является сопоставлением по умолчанию для Unicode в MySQL, если вы хотите использовать utf8_unicode_ci, вам придется указывать его во многих местах.
Например, все клиентские соединения имеют не только кодировку по умолчанию (имеет смысл для меня), но также и параметры сортировки по умолчанию (т. Е. Параметры сортировки всегда будут по умолчанию utf8_general_ci для юникода).
Вероятно, если вы используете utf8_unicode_ci для своих полей, ваши скрипты, которые подключаются к базе данных, должны быть обновлены, чтобы явно указывать желаемое сопоставление - в противном случае запросы, использующие текстовые строки, могут потерпеть неудачу, когда ваше соединение использует сопоставление по умолчанию.
В результате при преобразовании существующей системы любого размера в Unicode / utf8 может возникнуть необходимость использовать utf8_general_ci из-за того, что MySQL обрабатывает значения по умолчанию.
источник
Для случая, выделенного Guus, я настоятельно рекомендую использовать utf8_unicode_cs (чувствительный к регистру, строгое соответствие, правильное упорядочение по большей части) вместо utf8_bin (строгое соответствие, неправильное упорядочение).
Если поле предназначено для поиска, а не для пользователя, то используйте utf8_general_ci или utf8_unicode_ci. Оба регистрозависимы, одно совпадение будет проигрышным («ß» равно «s», а не «ss»). Существуют также языковые версии, такие как utf8_german_ci, где сопоставление с потерями больше подходит для указанного языка.
[Редактировать - почти 6 лет спустя]
Я больше не рекомендую набор символов «utf8» в MySQL, а вместо этого рекомендую набор символов «utf8mb4». Они почти полностью совпадают, но допускают немного (намного) больше символов Юникода.
Реально, MySQL должен был обновить набор символов «utf8» и соответствующие параметры сортировки, чтобы соответствовать спецификации «utf8», но вместо этого - отдельный набор символов и соответствующие параметры сортировки, чтобы не влиять на обозначение хранилища для тех, кто уже использует их неполный набор символов «utf8». ,
источник
utf8_unicode_cs
не существует. Единственный чувствительный к регистру utf8 этоutf8_bin
. Проблема вutf8_bin
сортировке неверна. См .: stackoverflow.com/questions/15218077/…Я нашел эти таблицы сравнения полезными. http://collation-charts.org/mysql60/ . Я не уверен, что используется utf8_general_ci, хотя.
Например, вот график для utf8_swedish_ci. Он показывает, какие символы он интерпретирует как одинаковые. http://collation-charts.org/mysql60/mysql604.utf8_swedish_ci.html
источник
В файле загрузки базы данных добавьте следующую строку перед любой строкой:
И ваша проблема должна быть решена.
источник
SET NAMES
запроса напрямую не дает клиенту знать о кодировке и может очень тонко нарушать некоторые функции, такие как подготовленные операторы.