Длина MySQL VARCHAR и UTF-8

84

В MySQL, если я создаю новое VARCHAR(32)поле в таблице UTF-8, означает ли это, что я могу хранить 32 байта данных в этом поле или 32 символа (многобайтовые)?

Аликс Аксель
источник
@naXa: Я этого не делал. Думаешь, мне следует?
Аликс Аксель
Не знаю.) Это ваш вопрос, и решать вам. Я просто хотел сказать, что «другой ответ выглядит более полным».
naXa 08
@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 символа.

M коричневый
источник
48
М Браун, спасибо, что упомянули об этом. Поле VARCHAR (10) (с использованием utf8mb4) может хранить «💩💩💩💩💩💩💩💩💩💩» (10 стопок пу), то есть 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

jspcal
источник
Я почти никогда не использую, CHARи когда я использую, он не предназначен для хранения многобайтовых символов, поэтому я в безопасности. А как насчет того VARCHAR, уверены ли вы, что ограничение определяется для многобайтовых символов, а не для однобайтовых символов?
Аликс Аксель,
9
@jspcal: UTF-8 использует максимум 4 байта на символ, а не 3. Или MySQL не поддерживает все 4 байта?
Реми Лебо
5
@RemyLebeau Вы правы насчет utf8, но не для MySQL. Различные наборы символов utf8_xxx имеют максимум 3 байта. Utf8mb4_xxx принимает 4 байтовых символа. dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Баттл Буткус
С течением времени похоже, что 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 03
5
Это неправильно, по крайней мере, для MySQL 5+. При указании размера столбца для varchar или char он указывается в символах. Я считаю, что фактический размер столбца VARCHAR (32) будет 32x3 + 1 = 97 байтов.
Баттл Буткус
5
@rjmackay '12345' не являются стандартными символами ASCII. en.wikipedia.org/wiki/…
Алексей Лебедев
7
Я вставил 40 символов Unicode в БД и усек до 32 символов. Но похоже, что люди думают, что я использовал байты ascii, и их усекают до 32 байтов. Неудивительно, что я получил отрицательные голоса, лол.
YOU
2
@ButtleButkus "Я считаю, что фактический размер столбца VARCHAR (32) будет 32x3 + 1 = 97 байтов". Это было бы, если бы вы использовали utf8, но тогда у вас будет нарушена поддержка Unicode в MySQL. utf8mb4Вместо этого вы должны использовать кодировку, потому что макс. 4 байта в символе utf-8 , а не 3, как в варианте MySQL для utf8 ...
Stijn de Witt
1

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

Подтолкнуть
источник
1
Я читал, что если ЛЮБОЙ столбец в таблице является varchar, вы теряете все преимущества наличия столбцов char. В принципе, кажется, что вам нужно использовать все varchar или все char в таблице для максимальной выгоды. Но я не знаю, правда ли это.
Баттл Буткус
Для 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, но на самом деле это вторая причина того же эффекта.

Лоран Ляуде
источник