UTF-8: Allgemein? Behälter? Unicode?

279

Ich versuche herauszufinden, welche Sortierung ich für verschiedene Datentypen verwenden soll. 100% des Inhalts, den ich speichern werde, sind vom Benutzer eingereicht.

Nach meinem Verständnis sollte ich UTF-8 General CI (ohne Berücksichtigung der Groß- und Kleinschreibung) anstelle von UTF-8 Binary verwenden. Ich kann jedoch keine klare Unterscheidung zwischen UTF-8 General CI und UTF-8 Unicode CI finden.

  1. Sollte ich vom Benutzer eingereichte Inhalte in UTF-8 General- oder UTF-8 Unicode CI-Spalten speichern?
  2. Für welche Art von Daten wäre UTF-8 Binary anwendbar?
Dolph
quelle
16
Randnotiz , aber statt utf8, verwenden Sie utf8mb4stattdessen für volle UTF-8 - Unterstützung. Hier kommentieren, weil die Antworten auf diese beliebte Frage dies nicht ansprechen. mathiasbynens.be/notes/mysql-utf8mb4
Steven R. Loomis
Wenn Sie eine Fallfaltung mit Akzentempfindlichkeit wünschen, senden Sie bitte eine Anfrage an bugs.mysql.com .
Rick James
Oder klicken Sie auf "Affects Me" unter bugs.mysql.com/bug.php?id=58797 und fügen Sie einen Kommentar hinzu.
Rick James

Antworten:

299

Im Allgemeinen ist utf8_general_ci schneller als utf8_unicode_ci , aber weniger korrekt.

Hier ist der Unterschied:

Für jeden Unicode-Zeichensatz sind Operationen, die mit der _general_ci-Kollatierung ausgeführt werden, schneller als die für die _unicode_ci-Kollatierung . Beispielsweise sind Vergleiche für die Kollatierung utf8_general_ci schneller, aber etwas weniger korrekt als Vergleiche für utf8_unicode_ci. Der Grund dafür ist, dass utf8_unicode_ci Zuordnungen wie Erweiterungen unterstützt. Das heißt, wenn ein Zeichen mit Kombinationen anderer Zeichen verglichen wird. Zum Beispiel ist in Deutsch und einigen anderen Sprachen "ß" gleich "ss". utf8_unicode_ci unterstützt auch Kontraktionen und ignorierbare Zeichen. utf8_general_ci ist eine Legacy-Kollatierung, die keine Erweiterungen, Kontraktionen oder ignorierbaren Zeichen unterstützt. Es können nur Eins-zu-Eins-Vergleiche zwischen Zeichen durchgeführt werden.

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

Weitere Informationen finden Sie im folgenden Beitrag in den MySQL-Foren: http://forums.mysql.com/read.php?103,187048,188748

Utf8_bin: Sowohl utf8_general_ci als auch utf8_unicode_ci führen einen Vergleich ohne Berücksichtigung der Groß- und Kleinschreibung durch. Im Gegensatz dazu unterscheidet utf8_bin (unter anderem) zwischen Groß- und Kleinschreibung , da es die Binärwerte der Zeichen vergleicht.

Sagi
quelle
2
Ich denke, wenn Sie keinen guten Grund haben, _unicode_ci zu verwenden, dann verwenden Sie _general_ci.
Sagi
4
Dies beantwortet die Frage jedoch nicht wirklich ausführlich. Was ist der Unterschied zwischen diesen Kollatierungen genau?
Pekka
4
Sie haben Recht, der genaue Unterschied wird hier der Einfachheit halber nicht angegeben. Ich habe einen Link zu einem Beitrag mit dem genauen Unterschied hinzugefügt .
Sagi
Mit NB show collation;können Sie die Standardkollatierung für jeden Zeichensatz anzeigen. 5.1 wird utf8_general_cistandardmäßig für angezeigt utf8.
David Carboni
9
Gibt es Ressourcen, die den tatsächlichen Geschwindigkeitsunterschied zwischen den beiden Kollatierungen vertiefen würden? Sprechen wir von einem Leistungsabfall von 0,1% oder einem Leistungsabfall von 10%?
Emphram Stavanger
90

Sie sollten sich auch der Tatsache bewusst sein, dass mit utf8_general_ci bei Verwendung eines varchar-Felds als eindeutiger oder primärer Index das Einfügen von 2 Werten wie 'a' und 'á' einen doppelten Schlüsselfehler ergeben würde.

Alex Hepp
quelle
3
Vielen Dank, dies ist nützlich, um ähnliche Benutzernamen zu vermeiden (z. B. wenn "jose" vorhanden ist, möchte ich nicht, dass jemand anderes einen "josé" -Benutzer erstellt). Hinweis: Dies gilt auch für die meisten utf8-Kollatierungen (außer utf8_bin). Das sicherste / sicherste / umfassendste istutf8_unicode_ci
Costa
2
Ich verwende utf8_bin, wo Jose und José im Index unterschieden werden sollen. Beispiel: Eine Spalte, in der Such- / Ersetzungsvorgänge aufgezeichnet werden, in der der Benutzer möglicherweise nach José gesucht und durch Jose ersetzt hat. (Ich schreibe ein Tabellenkalkulationsprogramm)
Buttle Butkus
33
  • utf8_binvergleicht die Bits blind. Kein Fallklappen, kein Akzentabziehen.
  • utf8_general_civergleicht ein Byte mit einem Byte. Es werden Fallfalten und Akzententfernung durchgeführt, aber keine 2-Zeichen-Vergleiche: ijist ijin dieser Zusammenstellung nicht gleich .
  • utf8_*_ciist eine Reihe von sprachspezifischen Regeln, aber ansonsten wie unicode_ci. Einige Sonderfälle: Ç, Č, ch,ll
  • utf8_unicode_cifolgt einem alten Unicode-Standard für Vergleiche. ij= ij, aber ae! =æ
  • utf8_unicode_520_cifolgt einem neueren Unicode-Standard. ae=æ

In der Kollatierungstabelle finden Sie Details dazu, was in verschiedenen utf8-Kollatierungen gleich ist.

utf8, wie von MySQL definiert, ist auf die 1- bis 3-Byte-utf8-Codes beschränkt. Dies lässt Emoji und einige Chinesen aus. Sie sollten also wirklich zu wechseln, utf8mb4wenn Sie weit über Europa hinausgehen möchten.

Die obigen Punkte gelten utf8mb4nach geeigneter Rechtschreibänderung. Vorwärts gehen utf8mb4und utf8mb4_unicode_520_ciwerden bevorzugt.

  • utf16 und utf32 sind Varianten von utf8; es gibt praktisch keine Verwendung für sie.
  • ucs2 ist näher an "Unicode" als "utf8"; es hat praktisch keinen Sinn dafür.
Rick James
quelle
1
Zu "dranbleiben": 8.0-Kollatierungen zeigen, wie verschiedene Zeichen, Diphthongs usw. in den 8.0-utf8mb4-Kollatierungen verglichen werden. utf8 ist meistens das gleiche.
Rick James
Und 8.0-Kollatierungen sind deutlich schneller als 5.x.
Rick James
Es wäre schön, wenn auf dieser Seite oben utf8mb4_bin aufgeführt wäre. Ich weiß, dass es überhaupt keine Charakterübereinstimmung gibt, aber es ist gut für Neulinge.
Henk Poley
6

Wirklich, ich habe das Speichern von Werten wie 'é' und 'e' in einer Spalte mit eindeutigem Index getestet und sie verursachen doppelte Fehler sowohl bei 'utf8_unicode_ci' als auch bei 'utf8_general_ci'. Sie können sie nur in der sortierten Spalte 'utf8_bin' speichern.

Und MySQL-Dokumente (in http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html ) schlagen in ihren Beispielen die Sortierung 'utf8_general_ci' vor.

[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci
vitalii
quelle
1
Ich habe einen kurzen Test gemacht, und es scheint genau zu sein. Beide Kollatierungen verhalten sich gleich, wenn es um einen eindeutigen Schlüssel in einer Spalte und Werte mit Tildes und dergleichen geht.
MirroredFate
@MirroredFate OK, ich sollte dort hinzufügen, dass die Spalte einen eindeutigen Index haben sollte, um diesen Fehler zu verursachen. Das impliziert meine Antwort.
vitalii
3

Akzeptierte Antwort ist veraltet.

Wenn Sie MySQL 5.5.3+ verwenden, verwenden Sie utf8mb4_unicode_cistattdessen, utf8_unicode_cium sicherzustellen, dass die von Ihren Benutzern eingegebenen Zeichen keine Fehler verursachen.

utf8mb4unterstützt beispielsweise Emojis, während Sie utf8möglicherweise Hunderte von Fehlern im Zusammenhang mit der Codierung erhalten, wie z.

Incorrect string value: ‘\xF0\x9F\x98\x81…’ for column ‘data’ at row 1

Marwann
quelle
Diese Antwort (richtig) behebt Probleme mit der Codierung von Emoji (und einigen Chinesen). Die Frage scheint sich jedoch auf die Sortierung zu konzentrieren. utf8mb4_unicode_cibehandelt (glaube ich) alle Emoji als gleich. utf8mb4_unicode_520_cigibt Emoji einen Befehl.
Rick James