Довжини MySQL VARCHAR та UTF-8


84

У MySQL, якщо я створюю нове VARCHAR(32)поле в таблиці UTF-8, це означає, що я можу зберігати 32 байти даних у цьому полі або 32 символи (багатобайтові)?


@naXa: Я ні. Ти вважаєш, що я повинен?
Алікс Аксель

Не знаю.) Це ваше питання, і це залежить від вас. Я просто хотів сказати "інша відповідь виглядає більш повною".
naXa

@robsch Попередня прийнята відповідь була простою та правильною. Але за популярним попитом я прийняв той, який ти хочеш.
Алікс Аксель

Відповіді:


168

Ця відповідь з’явилася у верхній частині моїх результатів пошуку Google, але не була правильною:

Плутанина, мабуть, пов'язана з різними версіями mysql, що перевіряються.

  • Версія 4 підраховує байти
  • Версія 5 нараховує символи

http://dev.mysql.com/doc/refman/5.0/en/string-type-overview.html

MySQL інтерпретує специфікації довжини у визначеннях стовпців символів у символьних одиницях. (До MySQL 4.1 довжини стовпців інтерпретувались у байтах.) Це стосується типів CHAR, VARCHAR та TEXT.

Цікаво (я про це не думав), що на максимальну довжину стовпця varchar utf8 впливає наступним чином:

Ефективна максимальна довжина VARCHAR у MySQL 5.0.3 та пізніших версіях залежить від максимального розміру рядка (65 535 байт, який розподіляється між усіма стовпцями) та використовуваного набору символів. Наприклад, символи utf8 можуть вимагати до трьох байтів на символ, тому стовпець VARCHAR, що використовує набір символів utf8, може бути оголошений максимум до 21 844 символів.


48
М. Браун, дякую, що згадали про це. Поле VARCHAR (10) (з використанням utf8mb4) може зберігати "💩💩💩💩💩💩💩💩💩💩" (10 стосів poo), це 10 символів, але 40 байт.
basic6

3
Це. Це єдина правильна відповідь. Занадто багато людей вважають поведінку версії 4 євангелією.
Брендан Берд,

2
Прийнята відповідь також є правильною для MySQL 5 - введені числа насправді були частиною набору символів повної ширини і є багатобайтовими символами унікоду, як це також зазначав плакат, який він вставив "32 багатобайтові дані". Шкода, що багато людей неправильно зрозуміли.
user193130

Посилаючись на наступне джерело, я вважаю, що символу utf8 в даний час потрібно до 6 байт, тож десь від 1 до 6 байт. Це спричиняє найгірший випадок для максимального значення символу 10922. Я думаю. joelonsoftware.com/articles/Unicode.html
usumoio

1
@usumoio Наразі схоже, що MySQL використовує 3-байтовий варіант UTF-8, при цьому планується перехід на (стандартний) 4-байтовий варіант: dev.mysql.com/doc/refman/8.0/en/charset-unicode -utf8.html .
flow2k

8

це дозволить вам зберегти 32 багатобайтові символи

Щоб заощадити місце за допомогою UTF-8, використовуйте VARCHAR замість CHAR. В іншому випадку MySQL повинен зарезервувати три байти для кожного символу в стовпці CHAR CHARACTER SET utf8, оскільки це максимально можлива довжина. Наприклад, MySQL повинен зарезервувати 30 байт для стовпця CHAR (10) CHARACTER SET utf8.

http://dev.mysql.com/doc/refman/5.0/en/charset-unicode.html


Я майже ніколи не використовую, CHARі коли я це роблю, це не призначене для зберігання багатобайтових символів, тому я в безпеці. Що стосується VARCHAR, ви впевнені, що обмеження визначено в багатобайтових символах, а не в однобайтових символах?
Алікс Аксель

9
@jspcal: UTF-8 використовує максимум 4 байти на символ, а не 3. Або MySQL не підтримує всі 4 байти?
Remy Lebeau

5
@RemyLebeau Ви маєте рацію щодо utf8, але не для MySQL. Різні набори символів utf8_xxx мають максимум 3 байти. Utf8mb4_xxx займає 4 байтові символи. dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Butkus

З плином часу, схоже, MySQL нарешті використовуватиме стандартну 4-байтову версію (але ще не на момент написання статті): dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8 .html .
flow2k

6

32 мультибайтові дані для varchar(32)зіставлення utf8_unicode_ci, я щойно тестував за допомогою XAMPP.

1234567890123456789012345678901234567890

Зрізати до:

12345678901234567890123456789012

Майте на увазі, що це не звичайні символи ASCII.


4
У UTF-8 стандартні символи ASCII зберігатимуться лише в одному байті - щоб реально перевірити це, вам потрібно фактично використовувати кілька багатобайтових (тобто не-ascii) символів у вашому тестовому жалі.
rjmackay

5
Це неправильно, принаймні для MySQL 5+. При зазначенні розміру стовпця для varchar або char він вказується з точки зору символів. Я вважаю, що фактичний розмір стовпця VARCHAR (32) буде 32x3 + 1 = 97 байт.
Buttle Butkus

5
@rjmackay '12345' не є стандартними символами ASCII. en.wikipedia.org/wiki/…
Олексій Лебедєв

7
Я вставив 40 символів Unicode в БД і отримав усічення на 32 символи. Але схоже на те, що люди думають, що я використовував байти ascii, і усікаю їх на 32 байти. Не дивно, я отримав голоси проти, ха-ха.
ВИ

2
@ButtleButkus "Я вважаю, що фактичний розмір стовпця VARCHAR (32) буде 32x3 + 1 = 97 байт" Це було б, якщо ви використовуєте utf8, але тоді ви отримуєте непрацюючу підтримку Unicode в MySQL. utf8mb4Натомість слід використовувати кодування, оскільки існує макс. 4 байта в символі utf-8 , а не 3, як у варіанті utf8 у MySQL ...
Stijn de Witt

1

Краще використовувати "char" для таблиць частого оновлення, оскільки загальна довжина даних рядка буде фіксованою та швидкою. Стовпці Varchar роблять розміри даних рядків динамічними. Це не добре для MyISAM, але я не знаю про InnoDB та інші. Наприклад, якщо у вас дуже вузький стовпець "типу", може бути краще використовувати char (2) з кодом latin1, щоб вимагати лише мінімальний простір.


1
Я читав, що якщо БУДЬ-ЯКИЙ стовпець у таблиці є varchar, то ви втрачаєте всі переваги наявності стовпців char. В основному, здається, вам доведеться йти з усіма varchar або всі char в таблиці для максимальної вигоди. Але я не знаю, чи це правда.
Buttle Butkus

Щодо MyISAM є певний аргумент за CHAR. Для InnoDB відбувається так багато інших речей, що дискусія щодо "динамічного / фіксованого розміру рядка" по суті не має значення.
Рік Джеймс

ІМХО важливим моментом тут є те, що для дуже малих довжин це може бути корисно використовувати CHAR.
ToolmakerSteve

0

Якщо ви підключаєтесь до бази даних за допомогою кодування latin1 (наприклад, з PHP), щоб зберегти рядок PHP UTF8 у стовпці MySQL UTF8, ви отримаєте подвійне кодування UTF8.

Якщо рядок UTF8 $sмає довжину 32 символи, але довжина - 64 байти, а стовпець VARCHAR(32)UTF8, подвійне кодування перетворить рядок у рядок $sUTF8 довжиною 64 символи, який буде усічений у базі даних до 32 перших символів, що відповідають 32 першим байтам з $s. Ви можете в кінцевому підсумку думати, що MySQL 5 поводиться як MySQL 4, але насправді це друга причина такого самого ефекту.

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