Чи слід використовувати Latin-1 над UTF-8, якщо мова йде про конфігурацію бази даних?


65

Ми використовуємо MySQL в компанії, в якій я працюю, і ми створюємо як клієнтські, так і внутрішні додатки, використовуючи Ruby on Rails.

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

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

Єдиний аргумент, який я чув, щоб дотримуватися латиниці-1, це те, що дозволяючи недрукувальні символи UTF-8 можуть зіпсувати пошук тексту та повнотекстові пошуки в MySQL. Це справді правда?

Чи є інші причини, що слід використовувати латинську-1 над UTF-8? Наскільки я розумію, що вона є вищою і стає всюдисущою.


4
@jon LATIN-1 не є англійською мовою. Там ідеально міститься іспанська, а також французька, якщо я не помиляюся.
Darkhogg

4
@Darkhog: Latin1 дійсно не є специфічним для англійської мови, але він по суті обмежений для західноєвропейських алфавітів.
Барт ван Іґен Шенау

16
Єдина можлива вигода від використання латинської 1, а не UTF-8 в сучасній системі - це диверсія. Це, звичайно, лише користь для диверсанта, і хто б не був їх лояльністю, а не власникам або розробникам системи.
Джон Ханна

13
Шкода, що ваша база даних не змогла б утримувати символ євро чи навіть моє ім’я (דותן).
dotancohen

20
користувач "копіює та вставляє" символи, які не є латинськими-1? не ставтесь до unicode як до якоїсь неактуальної легковажної речі, про яку піклуються лише пустотливі нерви. досить багато з нас набирають символів, які не підходять латині-1 регулярно - я чую, як багато людей розмовляють неєвропейськими мовами, навіть ♥
Eevee

Відповіді:


131

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

Найголовніша причина, чому ви повинні підтримувати Unicode - це те, що ви не повинні робити зайвих припущень щодо введення користувача. Я поняття не маю, що це ваш домен, але такі речі, як івритські імена користувачів, публікація в блозі про Китай, коментар з Emoji або просто добре стилізований текст - на кшталт "це" - повинні бути можливі ... О, це були типографічно правильні лапки ( “”а не ""), загальні тире та еліпсис, які є символами, які є загальними в англійському тексті, але не підтримуються ASCII або Latin-1. Тож підтримка інших сценаріїв не є просто великим f * ck до інших культур, але дотримання латиніни-1 навіть не дозволяє писати належну англійську мову.

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

Unicode також додає безліч недрукованих символів - але навіть ASCII містить їх безліч. Чи будете ви обробляти NUL посеред рядка? Як щодо 0x1C, "файлового сепаратора"? Я ніколи не бачив половини таких . Латинська-1 додає м'який дефіс, який вказує на можливості перелому слова, але інакше невидимий. Це також порушує ваш повнотекстовий пошук? Іншими словами, навіть ASCII та латинська-1 дозволяють вам повністю порушити свої дані, якщо ви припускаєте, що це все лише текст для друку!


8
З точки зору бази даних, деякі з цих символів не / повинні бути дозволені у полі типу тексту (text / varchar / char / тощо). MySQL дійсно дозволяє нульові символи в цих типах даних, але і інші бази даних , як PostgreSQL немає. Ви повинні використовувати BLOB (MySQL) або BYTEA (PostgreSQL), якщо хочете зберігати такі символи.
cimmanon

15
"Дотримуючись латиниці-1 навіть не дозволяє написати належну англійську мову" Це добре, інакше unicode буде протистояти ще сильніше. ;-)
Дедуплікатор

3
@ PaŭloEbermann Вбудовані символи NUL означають, що ваші дані - це двійкова крапка, а не просто рядок. NULs був дивним прикладом, оскільки я вважаю, що UTF-8 уникає використання \0байта як частини багатобайтового кодування, щоб переконатися, що код, не знаючий UTF8, не зупиняється посередині рядка.
Пітер Кордес

7
Усі символи Unicode можна надрукувати - вам просто потрібен правильний шрифт :-)
James Anderson

4
@JamesAnderson шрифт буде неправильним і порушеним. en.wikipedia.org/wiki/Unicode_control_characters
djechlin

62

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

Оскільки його позиція не повністю виходить до обіду, просто застаріла, поважайте його позицію, обговорюючи цю справу (і вам потрібно пам’ятати, щоб обговорювати , а не сперечатися), і намагайтеся розглянути питання , пов'язані з UTF-8. Я підозрюю, що основне питання не є технічним питанням, і це може зажадати певного рівня переговорів з обмеженими навичками.


6
Я не міг схвалити більше. Насправді я шкодую, що у власній відповіді я повністю проігнорував "людську сторону", що в цьому питанні цілком може бути першочерговим. Бажаю, щоб я міг подати заявку не раз :-)
LSerni

2
називати все, що не входить до латиниці-1, bad characterі думаєш, що non-printableце just out-datedти?
njzk2

2
Справжня проблема полягає в тому, "чи це технічне питання, з яким ми маємо справу?" Я не вірю, що начальник ОП ходив до школи і вчив цього, чи прочитав якийсь технічний посібник / журнал і прийшов до цього висновку. Я не розумію, що рішення є суто технічним рішенням. За іронією долі коментар показує саме серце проблеми; вирішення цього питання може бути вкрай образливим, якщо зроблено неналежним чином.
Нельсон

49

Хто з нас прав?

Колись ваш начальник був. Але з часом все змінюється. Сьогодні ви є (але перед тим, як бігти до свого начальника, обов’язково прочитайте відповідь Нельсона теж ).

Старі версії MySQL і старі версії здебільшого у всіх справлялися набагато краще зі старими Latin1 / ISO-8859-1 (5), ніж UTF8.

Існує причина, чому UTF8 створювався, розвивався та просувався здебільшого скрізь: якщо правильно його впровадити, він працює набагато краще . Існують деякі проблеми з продуктивністю та зберіганням, що випливають з того, що символ Latin1 дорівнює 8 бітам, тоді як символ UTF8 може бути від 8 до 32 біт. Тож при плануванні VARCHARпотрібно це враховувати. А ваші пошукові процедури будуть в рази повільнішими. Вони будуть в змозі зробити більше речей (наприклад , пошук з чутливістю акцентом чи без . Не можу робити ті , в Latin1 без великої роботи), але вони будуть приймати трохи більше часу.

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

Можливо, вам доведеться турбуватися про інструменти пошуку тощо, якщо ви розробляли такі інструменти. Але ти, мабуть, ні. Ви використовуєте ці інструменти; навіть ті, які вчора не були повністю сумісні з UTF8 (як раніше не було MySQL), є сьогодні, або незабаром будуть (наприклад, MySQL з підтримкою utf8mb4).

Таким чином, ретельно спланувавши та застосувавши правильний шлях UTF8 ( не постукувавши його по Latin1 як заздалегідь), ви можете отримати код, який є дуже розумним у майбутньому , який, якщо ви плануєте коли-небудь вести бізнес з будь-якою азіатською країною, - це дуже добре Річ. І якщо у вас немає таких планів, у інших людей з’являться, і ці люди можуть бути вашими замовниками, постачальниками чи партнерами.

Отже, коли вони почнуть надсилати вам дані UTF8, вам доведеться встановити складну річamajig для перетворення на Latin-1 та вирішення нерозв'язних справ.

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


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. Це єдиний вид, щоб правити всіма текстами у світі.


MySQL спробує перетворити дані в кодування бази даних, перш ніж перетворити їх у кодування стовпців. Якщо у вас є клієнт utf8, база даних latin1 та colfut utf8, текстові дані можуть бути втрачені.
Іван Солнцев

Іване, це зовсім інше питання. Взаємодія між набором символів-клієнтом, сервером набору символів, з'єднанням набір символів, набором символів-результатів є довгою статтею в документації MySQL. А у випадку параметрів зіставлення за стовпцями "зіставлення бази даних" - це зіставлення стовпців, і воно безпосередньо перетворюється на результат набору символів, ігноруючи зіставлення бази даних.
AnrDaemon

0

Просто поясніть йому, що UTF-8 є типовим для веб-трафіку. І будь-який користувач може ввести будь-який дійсний символ Unicode у своєму браузері.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.