Długości MySQL VARCHAR i UTF-8

84

W MySQL, jeśli utworzę nowe VARCHAR(32)pole w tabeli UTF-8, czy oznacza to, że mogę przechowywać 32 bajty danych w tym polu lub 32 znaki (wielobajtowe)?

Alix Axel
źródło
@naXa: Nie zrobiłem. Myślisz, że powinienem?
Alix Axel
Nie wiem.) To jest twoje pytanie i zależy od ciebie. Chciałem tylko powiedzieć, że „inna odpowiedź wygląda na bardziej kompletną”.
naXa
@robsch Poprzednio zaakceptowana odpowiedź była prosta i poprawna. Ale rób na popularne żądanie, zaakceptowałem ten, który chcesz.
Alix Axel

Odpowiedzi:

168

Ta odpowiedź pojawiła się u góry moich wyników wyszukiwania Google, ale nie była poprawna, więc:

Zamieszanie jest prawdopodobnie spowodowane testowaniem różnych wersji mysql.

  • Wersja 4 liczy bajty
  • Wersja 5 liczy znaki

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

MySQL interpretuje specyfikacje długości w definicjach kolumn znakowych w jednostkach znakowych. (Przed MySQL 4.1 długości kolumn były interpretowane w bajtach). Dotyczy to typów CHAR, VARCHAR i TEXT.

Co ciekawe (nie myślałem o tym) utf8 wpływa na maksymalną długość kolumny varchar w następujący sposób:

Efektywna maksymalna długość VARCHAR w MySQL 5.0.3 i nowszych jest zależna od maksymalnego rozmiaru wiersza (65 535 bajtów, który jest wspólny dla wszystkich kolumn) i używanego zestawu znaków. Na przykład znaki utf8 mogą wymagać do trzech bajtów na znak, więc kolumna VARCHAR, która używa zestawu znaków utf8, może mieć maksymalnie 21 844 znaków.

M Brown
źródło
48
M Brown, dzięki za wspomnienie o tym. Pole VARCHAR (10) (przy użyciu utf8mb4) może przechowywać „💩💩💩💩💩💩💩💩💩💩” (10 stosów poo), czyli 10 znaków, ale 40 bajtów.
basic6
3
To. To jedyna prawidłowa odpowiedź. Zbyt wiele osób uważa, że ​​zachowanie wersji 4 jest ewangelią.
Brendan Byrd,
2
Zaakceptowana odpowiedź jest również poprawna dla MySQL 5 - wstawione liczby były w rzeczywistości częścią zestawu znaków o pełnej szerokości i są wielobajtowymi znakami unicode, jak również wspomniał na plakacie, że wstawił „32 wielobajtowe dane”. Szkoda, że ​​tak wielu ludzi źle zrozumiało.
user193130
Powołując się na następujące źródło, uważam, że znak utf8 wymaga obecnie do 6 bajtów, czyli od 1 do 6 bajtów. To powoduje, że w najgorszym przypadku maksymalna liczba znaków to 10922. Myślę. joelonsoftware.com/articles/Unicode.html
usumoio
1
@usumoio Obecnie wygląda na to, że MySQL używa 3-bajtowego wariantu UTF-8, z planowaną migracją do (standardowego) 4-bajtowego wariantu: dev.mysql.com/doc/refman/8.0/en/charset-unicode -utf8.html .
flow2k
8

pozwoliłoby ci to zapisać 32 wielobajtowe znaki

Aby zaoszczędzić miejsce dzięki UTF-8, użyj VARCHAR zamiast CHAR. W przeciwnym razie MySQL musi zarezerwować trzy bajty dla każdego znaku w kolumnie CHAR CHARACTER SET utf8, ponieważ jest to maksymalna możliwa długość. Na przykład MySQL musi zarezerwować 30 bajtów dla kolumny CHAR (10) CHARACTER SET utf8.

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

jspcal
źródło
Prawie nigdy nie używam, CHARa kiedy to robię, nie jest to przeznaczone do przechowywania znaków wielobajtowych, więc jestem bezpieczny. A co z tym VARCHAR, czy na pewno limit jest zdefiniowany w znakach wielobajtowych, a nie w znakach jednobajtowych?
Alix Axel
9
@jspcal: UTF-8 wykorzystuje maksymalnie 4 bajty na znak, a nie 3. A może MySQL nie obsługuje wszystkich 4 bajtów?
Remy Lebeau,
5
@RemyLebeau Masz rację co do utf8, ale nie do MySQL. Różne zestawy znaków utf8_xxx mają maksymalnie 3 bajty. Utf8mb4_xxx przyjmuje 4 znaki bajtowe. dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Buttle Butkus
Wraz z upływem czasu wygląda na to, że MySQL w końcu użyje standardowej 4-bajtowej wersji (ale jeszcze nie w momencie pisania): dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8 .html .
flow2k
6

32 wielobajtowe dane varchar(32)z sortowaniem utf8_unicode_ci, właśnie przetestowałem z XAMPP.

1234567890123456789012345678901234567890

Skróć do:

12345678901234567890123456789012

Pamiętaj, że nie są to zwykłe znaki ASCII.

TY
źródło
4
W standardzie UTF-8 znaki ASCII będą przechowywane tylko w jednym bajcie - aby naprawdę to przetestować, musisz faktycznie użyć kilku znaków wielobajtowych (tj. Innych niż ascii) w swoim żądaniu testowym.
rjmackay
5
To jest złe, przynajmniej w przypadku MySQL 5+. Podczas określania rozmiaru kolumny dla varchar lub char, jest on określany w postaci znaków. Uważam, że rzeczywisty rozmiar kolumny VARCHAR (32) wyniósłby 32x3 + 1 = 97 bajtów.
Buttle Butkus
5
@rjmackay '12345' nie są standardowymi znakami ASCII. en.wikipedia.org/wiki/…
Alexey Lebedev
7
Wstawiłem 40 znaków Unicode do DB i zostałem obcięty do 32 znaków. Ale wygląda na to, że ludzie myślą, że użyłem bajtów ascii i zostałem obcięty do 32 bajtów. Nic dziwnego, mam głosy negatywne, lol.
TY
2
@ButtleButkus "Uważam, że rzeczywisty rozmiar kolumny VARCHAR (32) wyniósłby 32x3 + 1 = 97 bajtów" Byłoby, gdybyś używał utf8, ale wtedy otrzymujesz zepsutą obsługę Unicode w MySQL. Zamiast tego powinieneś użyć utf8mb4kodowania, ponieważ istnieje maks. 4 bajty w znaku utf-8 , a nie 3, jak w wariancie utf8 w MySQL ...
Stijn de Witt
1

Lepiej jest używać znaku „char” w przypadku często aktualizowanych tabel, ponieważ całkowita długość danych wiersza zostanie ustalona i szybka. Kolumny Varchar sprawiają, że rozmiary danych wierszy są dynamiczne. To nie jest dobre dla MyISAM, ale nie wiem o InnoDB i innych. Na przykład, jeśli masz bardzo wąską kolumnę „typ”, może być lepiej użyć znaku char (2) z zestawem znaków latin1, aby zająć tylko minimalną ilość miejsca.

Szturchać
źródło
1
Czytałem, że jeśli DOWOLNA kolumna w tabeli to varchar, tracisz wszystkie korzyści płynące z posiadania kolumn typu char. Zasadniczo wydaje się, że aby uzyskać maksymalne korzyści, musisz wybrać wszystkie varchar lub wszystkie char w tabeli. Nie wiem jednak, czy to prawda.
Buttle Butkus
Dla MyISAM jest kilka argumentów za CHAR. W przypadku InnoDB dzieje się tak wiele innych rzeczy, że debata „dynamiczny / stały rozmiar wiersza” jest zasadniczo nieistotna.
Rick James
IMHO ważną kwestią jest to, że w przypadku bardzo małych długości może być korzystne użycie CHAR.
ToolmakerSteve
0

Jeśli połączysz się z bazą danych przy użyciu kodowania latin1 (na przykład z PHP), aby zapisać ciąg PHP UTF8 w kolumnie MySQL UTF8, będziesz mieć podwójne kodowanie UTF8.

Jeśli łańcuch UTF8 $sma 32 znaki, ale 64 bajty, a kolumna ma VARCHAR(32)format UTF8, podwójne kodowanie spowoduje konwersję ciągu $sna 64-znakowy ciąg UTF8, który zostanie obcięty w bazie danych do jego 32 pierwszych znaków odpowiadających 32 pierwszym bajtom z $s. Możesz pomyśleć, że MySQL 5 zachowuje się jak MySQL 4, ale w rzeczywistości jest to druga przyczyna tego samego efektu.

Laurent Lyaudet
źródło