Следует ли использовать Latin-1 поверх UTF-8, когда речь идет о конфигурации базы данных?

65

Мы используем MySQL в компании, в которой я работаю, и мы создаем как клиентские, так и внутренние приложения, используя Ruby on Rails.

Когда я начал работать здесь, я столкнулся с проблемой, с которой я никогда не сталкивался раньше; база данных на производственном сервере установлена ​​на Latin-1, что означает, что гем MySQL выдает исключение всякий раз, когда есть пользовательский ввод, когда пользователь копирует и вставляет символы UTF-8.

Мой босс называет их «плохими персонажами», так как большинство из них - непечатные символы, и говорит, что мы должны их убрать. Я нашел несколько способов сделать это, но в итоге мы оказались в ситуации, когда требовался символ UTF-8. Кроме того, это немного хлопотно, тем более что кажется, что единственное решение, о котором я когда-либо читал для этой проблемы, - это просто установить для базы данных UTF-8 (имеет смысл для меня).

Единственный аргумент, который я слышал о том, что придерживаюсь Latin-1, это то, что использование непечатных символов UTF-8 может испортить текстовый / полнотекстовый поиск в MySQL. Это правда?

Есть ли другие причины, по которым стоит использовать Latin-1 вместо UTF-8? Насколько я понимаю, он превосходит и становится все более вездесущим.

Ravenstine
источник
4
@jon LATIN-1 не является специфическим для английского языка. Испанский там прекрасно содержится, а также французский, если я не ошибаюсь.
Darkhogg
4
@Darkhog: Latin1 действительно не специфичен для английского языка, но по существу он ограничен западноевропейскими алфавитами.
Барт ван Инген Шенау
16
Единственная возможная выгода от использования Latin 1 вместо UTF-8 в современной системе - это саботаж. Это, конечно, является только выгодой для диверсанта и всех, кто их лояльны, а не для владельцев или разработчиков системы.
Джон Ханна
13
Жаль, что ваша база данных не сможет содержать символ евро или даже мое имя (דותן).
Dotancohen
20
пользователь "копирует и вставляет" нелатинские символы-1? не рассматривайте юникод как какую-то несущественную легкомысленную вещь, о которой заботятся только вредные ботаники. довольно многие из нас пишут символы, которые не вписываются в латиницу-1 на регулярной основе - я слышал, что многие люди говорят на неевропейских языках, даже ♥
Eevee

Ответы:

130

Unicode, безусловно, сложен, а кодировка UTF-8 обладает парой неудобных свойств. Тем не менее, UTF-8 стал де-факто стандартной кодировкой в ​​сети, превзойдя ASCII, Latin-1, UCS-2 и UTF-16. Просто используйте UTF-8 везде .

Самая важная причина, по которой вам следует поддерживать Unicode, заключается в том, что вы не должны делать ненужных предположений относительно пользовательского ввода. Я понятия не имею, какой у вас домен, но такие вещи, как имена пользователей на иврите, запись в блоге о Китае, комментарий с Emoji или просто хорошо оформленный текст - например, «это» - должны быть возможны… О, это были типографски правильные кавычки ( “”вместо ""), широкие тире и многоточие, которые являются символами, которые являются общими в английском тексте, но не поддерживаются ASCII или Latin-1. Таким образом, отказ от поддержки других сценариев - это не просто большой урок для других культур, но придерживаться Latin-1 даже не позволяет вам писать на правильном английском языке.

Понятие, что Юникод допускает только «плохие символы», неверно. Да, текст действительно сложен, и Unicode не будет скрывать это от вас. Ваш начальник может думать о составных символах, когда одна базовая кодовая точка, такая как a, модифицируется последующими кодовыми точками, которые, например, представляют диакритические знаки, образуя один визуальный символ, такой как á. Это на самом деле не мешает вам при поиске, если вы делаете какую-то нормализацию. Например, вы можете сохранить весь текст в форме NFC, которая сворачивает такие композиции в предварительно составленную форму, если она доступна. При выполнении поиска вы также можете убрать все составные символы из текста, но это может существенно изменить их значение в некоторых языках.

Юникод также добавляет много непечатаемых символов - но даже в ASCII их много. Будете ли вы обрабатывать NUL в середине строки? Как насчет 0x1C, «Разделитель файлов»? Я никогда не видел половину из них . В латинице-1 добавлен мягкий дефис, указывающий на возможности разрыва слова, но в остальном он невидим. Это также нарушает ваш полнотекстовый поиск? Другими словами, даже ASCII и Latin-1 позволяют полностью прервать ввод, если вы предполагаете, что это всего лишь печатный текст!

Амон
источник
8
С точки зрения базы данных, некоторые из этих символов не допускаются / не должны быть разрешены в поле типа текста (text / varchar / char / etc.). MySQL действительно позволяет нулевые символы в этих типах данных, но и другие базы данных , как PostgreSQL нет. Вы должны использовать BLOB (MySQL) или BYTEA (PostgreSQL), если хотите иметь возможность хранить такие символы.
Цимманон
15
«придерживаясь Latin-1, вы даже не можете писать на английском». Это хорошо, иначе юникод будет сопротивляться еще сильнее. ;-)
Дедупликатор
3
@ PaŭloEbermann Встроенные NUL-символы означают, что ваши данные представляют собой двоичный двоичный объект, а не просто строку. NUL были странным примером, поскольку я считаю, что UTF-8 избегает использования \0байта как части многобайтовой кодировки, чтобы убедиться, что код, не поддерживающий UTF8, не останавливается в середине строки.
Питер Кордес
7
Все символы Юникода доступны для печати - вам просто нужен правильный шрифт :-)
Джеймс Андерсон
4
@JamesAnderson шрифт будет неправильным и сломанным. en.wikipedia.org/wiki/Unicode_control_characters
Джехлин
62

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

Так как его позиция не полностью готова к обеду, просто устарела, уважайте его позицию при обсуждении этого вопроса (и вы должны помнить, чтобы обсуждать , а не спорить), и попытайтесь решить проблемы, которые у него есть в отношении UTF-8. Я подозреваю, что основная проблема не является технической проблемой и может потребовать определенного уровня согласования мягких навыков.

нельсон
источник
6
Я не мог одобрить больше. На самом деле я сожалею, что в своем собственном ответе я полностью упустил из виду «человеческую сторону», которая в этом вопросе вполне может быть первостепенной. Хотелось бы, чтобы я проголосовал более одного раза :-)
LSerni
2
звонить всем за пределами латиницы bad characterи думать, что non-printableэто just out-datedдля вас?
njzk2
2
Реальная проблема заключается в том, "Это техническая проблема, с которой мы имеем дело?" Я не верю, что начальник ОП ходил в школу и обучался этому, или читал какое-то техническое руководство / журнал и пришел к такому выводу. Я не понимаю, что решение является чисто техническим решением. По иронии судьбы комментарий показывает именно суть проблемы; решение этой проблемы может быть чрезвычайно оскорбительным, если сделано неправильно.
Нельсон
49

Кто из нас прав?

Когда-то ваш босс был. Но со временем все меняется. В настоящее время, вы есть (но прежде чем бежать к своему боссу, обязательно прочитайте ответ Нельсона ).

Старые версии MySQL и старые версии, в основном все , работали с более старой Latin1 / ISO-8859-1 (5), чем с UTF8.

Существует причина, по которой UTF8 создавался, развивался и распространялся в основном везде: при правильной реализации он работает намного лучше . Существуют некоторые проблемы с производительностью и хранением, связанные с тем, что символ Latin1 имеет длину 8 бит, а символ UTF8 может иметь длину от 8 до 32 бит. Поэтому при планировании VARCHARнеобходимо учитывать это. И ваши поисковые процедуры будут немного медленнее. Они будут в состоянии делать больше вещей (например, поиск с чувствительностью к акценту или без . Не могут сделать это на латыни 1 без большой работы), но они будут занимать немного больше времени.

Но, с другой стороны, хранилище дешево , реалистичные издержки на размеры файлов составляют менее 2-3%, вычислительная мощность также дешева и дешевеет в соответствии с законом Мура; в то время как ваше время и ожидания ваших клиентов определенно не так .

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

Таким образом, тщательно спланировав и внедрив UTF8 правильным способом ( не обращая внимания на латиницу 1 в качестве запоздалой мысли), вы можете получить код, который очень разумно ориентирован на будущее , что, если вы планируете когда-либо вести бизнес с любой азиатской страной, является очень хорошим Вещь. И если у вас нет таких планов, другие люди будут иметь, и эти люди могут быть вашими клиентами, поставщиками или партнерами.

Поэтому, когда они начнут отправлять вам данные в формате UTF8, вам придётся настроить сложную вещь для преобразования в Latin1 и обратно, а также решать неразрешимые случаи.

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

LSerni
источник
4

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

Для любых других текстов просто используйте UTF-8.

Ли Райан
источник
2
Разве в MySQL нет перечислений?
raptortech97
2
А поскольку ASCII является подмножеством UTF8, просто используйте UTF8 даже тогда.
RemcoGerlich
@RemcoGerlich: я не согласен, что вы могли бы использовать UTF8 для них. На мой взгляд, внешние ссылки - это не текст, а непрозрачная последовательность байтов. У них нет кодировки, кроме удобства обозначения. Если последовательность байтов имеет интерпретацию в определенной кодировке, то это домен внешней системы или приложения, а не базы данных.
Ли Райан
3
@LieRyan: Я вижу этот момент, но тогда это не должен быть ASCII, вероятно, какой-то двоичный формат двоичных объектов или около того.
RemcoGerlich
3

Для начала, не важно, как настроен ваш сервер . Кодировка символов в MySQL может быть настроена для каждого столбца (значит, одна и та же таблица может содержать символы в нескольких кодировках, легко). Т.е. мой сервер (и несколько устаревших баз данных в нем) по умолчанию настроен для cp1251 для старых клиентов, которые не могут установить правильное сопоставление при подключении (разные аппаратные клиенты), но все основные базы данных в производстве используют UTF-8.

Говоря о «потраченном впустую пространстве» - вы не можете реально назвать важные данные пустой тратой, не так ли? Увеличение объема памяти, однако, будет отличаться в зависимости от языка, на котором находятся ваши данные. От незначительного (менее 1%) увеличения, если ваш сайт в основном на английском, и до 100%, если он почтовый с использованием символов вне диапазона ASCII , И даже больше, если вы двинетесь дальше на восток. Более поздние спецификации UTF-8 (так называемые UTF8mb4) допускают до 4 байтов на кодовую точку.

И "кто прав" ... На самом деле это социальный вопрос, а не технический. Могут быть веские причины для конкретных настроек сервера, но вы должны знать последствия. Но если вы спросите меня, нет причин не использовать UTF-8. Это единственный способ управлять всеми текстами в мире.

AnrDaemon
источник
MySQL попытается преобразовать данные в кодировку базы данных перед преобразованием в кодировку столбцов. Если у вас есть клиент utf8, база данных latin1 и столбец utf8, то текстовые данные могут быть потеряны.
Иван Солнцев
Иван, это совершенно другой вопрос. Взаимодействие между набором символов-клиентом, набором символов-сервером, набором символов-соединением, набором символов-результатами является длинной статьей в документации MySQL. А в случае параметров сортировки по столбцам «сортировка базы данных» - это сортировка столбцов, и она напрямую преобразуется в набор символов, игнорируя параметры сортировки базы данных.
AnrDaemon
0

Просто объясните ему, что UTF-8 используется по умолчанию для веб-трафика. И любой пользователь может ввести любой действительный символ Unicode в своем браузере.

Просто намного проще иметь utf-8 / unicode на всем пути от внешнего интерфейса до внутреннего, чем решать множество различных проблем, возникающих в результате использования utf-8-> latin-1-> utf-8.

Джеймс Андерсон
источник