MySQL VARCHAR Längen und UTF-8

83

Wenn ich in MySQL ein neues VARCHAR(32)Feld in einer UTF-8-Tabelle erstelle, bedeutet dies, dass ich 32 Datenbytes in diesem Feld oder 32 Zeichen (Multi-Byte) speichern kann?

Alix Axel
quelle
@naXa: Ich habe nicht. Du denkst ich sollte?
Alix Axel
Ich weiß es nicht.) Es ist deine Frage und es liegt an dir. Ich wollte nur sagen "eine andere Antwort sieht vollständiger aus".
NaXa
@robsch Die zuvor akzeptierte Antwort war einfach und richtig. Aber auf vielfachen Wunsch habe ich die akzeptiert, die Sie wollen.
Alix Axel

Antworten:

166

Diese Antwort wurde oben in meinen Google-Suchergebnissen angezeigt, war jedoch nicht korrekt.

Die Verwirrung ist wahrscheinlich darauf zurückzuführen, dass verschiedene Versionen von MySQL getestet werden.

  • Version 4 zählt Bytes
  • Version 5 zählt Zeichen

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

MySQL interpretiert Längenangaben in Zeichenspaltendefinitionen in Zeicheneinheiten. (Vor MySQL 4.1 wurden die Spaltenlängen in Bytes interpretiert.) Dies gilt für die Typen CHAR, VARCHAR und TEXT.

Interessanterweise (ich hatte nicht darüber nachgedacht) wird die maximale Länge einer Varchar-Spalte von utf8 wie folgt beeinflusst:

Die effektive maximale Länge eines VARCHAR in MySQL 5.0.3 und höher hängt von der maximalen Zeilengröße (65.535 Byte, die von allen Spalten gemeinsam genutzt wird) und dem verwendeten Zeichensatz ab. Beispielsweise können utf8-Zeichen bis zu drei Bytes pro Zeichen erfordern, sodass eine VARCHAR-Spalte, die den utf8-Zeichensatz verwendet, mit maximal 21.844 Zeichen deklariert werden kann.

M Brown
quelle
48
M Brown, danke, dass Sie dies erwähnt haben. Ein VARCHAR (10) -Feld (mit utf8mb4) kann "💩💩💩💩💩💩💩💩💩💩" (10 Stapel Poo) speichern, das sind 10 Zeichen, aber 40 Bytes.
basic6
3
Dies. Dies ist die einzig richtige Antwort. Viel zu viele Menschen glauben, dass das Verhalten von Version 4 ein Evangelium ist.
Brendan Byrd
2
Die akzeptierte Antwort ist auch für MySQL 5 korrekt - die eingegebenen Zahlen waren tatsächlich Teil des Zeichensatzes in voller Breite und sind Multi-Byte-Unicode-Zeichen, wie auch auf dem Poster erwähnt, dass er "32 Multibyte-Daten" eingefügt hat. Es ist eine Schande, dass so viele Menschen missverstanden haben.
user193130
Unter Berufung auf die folgende Quelle glaube ich, dass ein utf8-Zeichen derzeit bis zu 6 Bytes benötigt, also irgendwo zwischen 1 und 6 Bytes. Dies führt dazu, dass der schlechteste Fall für ein Zeichenmaximum 10922 beträgt. Ich denke. joelonsoftware.com/articles/Unicode.html
usumoio
1
@usumoio Derzeit sieht es so aus, als ob MySQL die 3-Byte-Variante von UTF-8 verwendet, wobei die Migration auf die (Standard-) 4-Byte-Variante geplant ist: dev.mysql.com/doc/refman/8.0/en/charset-unicode -utf8.html .
flow2k
8

Damit können Sie 32 Multi-Byte-Zeichen speichern

Verwenden Sie VARCHAR anstelle von CHAR, um mit UTF-8 Platz zu sparen. Andernfalls muss MySQL drei Bytes für jedes Zeichen in einer CHAR CHARACTER SET utf8-Spalte reservieren, da dies die maximal mögliche Länge ist. Beispielsweise muss MySQL 30 Bytes für eine CHAR (10) CHARACTER SET utf8-Spalte reservieren.

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

jspcal
quelle
Ich benutze es fast nie CHARund wenn ich es tue, ist es nicht beabsichtigt, Multi-Byte-Zeichen zu speichern, also bin ich sicher. Was ist mit VARCHAR, sind Sie sicher, dass das Limit in Mehrbyte-Zeichen und nicht in Einzelbyte-Zeichen definiert ist?
Alix Axel
9
@jspcal: UTF-8 verwendet maximal 4 Bytes pro Zeichen, nicht 3. Oder unterstützt MySQL nicht alle 4 Bytes?
Remy Lebeau
4
@RemyLebeau Sie haben Recht mit utf8, aber nicht mit MySQL. Die verschiedenen utf8_xxx-Zeichensätze sind maximal 3 Byte groß. Die utf8mb4_xxx nehmen 4-Byte-Zeichen an. dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html
Buttle Butkus
Im Laufe der Zeit wird MySQL anscheinend endlich die Standardversion mit 4 Byte verwenden (zum Zeitpunkt des Schreibens jedoch noch nicht): dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8 .html .
flow2k
6

32 Multibyte Daten für varchar(32)mit Sortierung habe utf8_unicode_ciich gerade mit XAMPP getestet.

1234567890123456789012345678901234567890

Abschneiden auf:

12345678901234567890123456789012

Beachten Sie, dass dies keine regulären ASCII-Zeichen sind.

SIE
quelle
4
In UTF-8 werden Standard-ASCII-Zeichen nur in einem einzigen Byte gespeichert. Um dies wirklich zu testen, müssen Sie tatsächlich einige Multibyte-Zeichen (dh Nicht-ASCII-Zeichen) in Ihrem Teststich verwenden.
rjmackay
5
Dies ist zumindest für MySQL 5+ falsch. Wenn Sie die Spaltengröße für varchar oder char angeben, wird diese in Zeichen angegeben. Ich glaube, die tatsächliche Größe einer VARCHAR (32) -Spalte wäre 32x3 + 1 = 97 Bytes.
Buttle Butkus
5
@rjmackay '12345' sind keine Standard-ASCII-Zeichen. en.wikipedia.org/wiki/…
Alexey Lebedev
7
Ich habe 40 Unicode-Zeichen in die Datenbank eingefügt und wurde auf 32 Zeichen abgeschnitten. Aber es sieht so aus, als ob die Leute denken, ich hätte ASCII-Bytes verwendet und werde bei 32 Bytes abgeschnitten. Kein Wunder, ich habe Downvotes bekommen, lol.
SIE
2
@ButtleButkus „Ich glaube , die tatsächliche Größe einer VARCHAR (32) Spalte 32x3 + 1 = 97 Byte groß sein würde“ es wäre , wenn Sie verwenden utf8, aber dann bekommen Sie Unicode - Unterstützung in MySQL gebrochen. Sie sollten utf8mb4stattdessen die Codierung verwenden, da max. 4 Bytes in einem utf-8-Zeichen , nicht 3 wie in MySQLs Variante von utf8 ...
Stijn de Witt
1

Es ist besser, "char" für häufig verwendete Aktualisierungstabellen zu verwenden, da die Gesamtdatenlänge der Zeile fest und schnell ist. Varchar-Spalten machen die Zeilendatengrößen dynamisch. Das ist nicht gut für MyISAM, aber ich weiß nichts über InnoDB und andere. Wenn Sie beispielsweise eine sehr schmale "Typ" -Spalte haben, ist es möglicherweise besser, char (2) mit latin1-Zeichensatz zu verwenden, um nur minimalen Speicherplatz zu beanspruchen.

Schubs
quelle
1
Ich habe gelesen, dass wenn jede Spalte in einer Tabelle varchar ist, Sie alle Vorteile von char-Spalten verlieren. Grundsätzlich scheint es, als müssten Sie mit allen varchar oder allen char in einer Tabelle gehen, um den größtmöglichen Nutzen zu erzielen. Ich weiß allerdings nicht, ob es stimmt.
Buttle Butkus
Für MyISAM gibt es ein Argument dafür CHAR. Für InnoDB sind so viele andere Dinge im Gange, dass die Debatte über "dynamische / feste Zeilengröße" im Wesentlichen irrelevant ist.
Rick James
IMHO ist der wichtige Punkt hier, dass für sehr kleine Längen die Verwendung vorteilhaft sein kann CHAR.
ToolmakerSteve
0

Wenn Sie mithilfe der Latin1-Codierung (z. B. mit PHP) eine Verbindung zur Datenbank herstellen, um eine PHP-UTF8-Zeichenfolge in einer MySQL-UTF8-Spalte zu speichern, haben Sie eine doppelte UTF8-Codierung.

Wenn die UTF8-Zeichenfolge $s32 Zeichen lang, aber 64 Byte lang ist und die Spalte VARCHAR(32)UTF8 ist, konvertiert die Doppelcodierung die Zeichenfolge $sin eine 64 Zeichen lange UTF8-Zeichenfolge, die in der Datenbank auf ihre 32 ersten Zeichen gekürzt wird, die den 32 ersten Bytes entsprechen von $s. Möglicherweise denken Sie, dass sich MySQL 5 wie MySQL 4 verhält, aber es ist tatsächlich eine zweite Ursache für denselben Effekt.

Laurent Lyaudet
quelle