2010-02-26 8 views
248

Ich versuche herauszufinden, welchen Vergleich ich für verschiedene Arten von Daten verwenden sollte. 100% des Inhalts, den ich speichern möchte, werden vom Benutzer übermittelt.UTF-8: Allgemein? Behälter? Unicode?

Mein Verständnis ist, dass ich UTF-8 General CI (Case-Insensitive) anstelle von UTF-8 Binary verwenden sollte. Allerdings kann ich keinen klaren Unterschied zwischen UTF-8 General CI und UTF-8 Unicode CI finden.

  1. Sollte ich von Benutzern eingereichte Inhalte in UTF-8 General oder UTF-8 Unicode CI-Spalten speichern?
  2. Für welche Art von Daten würde UTF-8 Binär anwendbar sein?
+9

Seitennotiz, anstelle von 'utf8', verwenden Sie stattdessen 'utf8mb4' für die volle UTF-8-Unterstützung. Kommentieren hier, weil die Antworten auf diese populäre Frage nicht darauf eingehen. https://mathiasbynens.be/notes/mysql-utf8mb4 –

+0

Wenn Sie Fall Faltung wollen, aber Akzent Empfindlichkeit, bitte eine Anfrage an http://bugs.mysql.com. –

+0

Oder klicken Sie auf "Affects Me" auf https://bugs.mysql.com/bug.php?id=58797 und fügen Sie einen Kommentar hinzu. –

Antwort

272

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

Hier ist der Unterschied:

Für alle Unicode-Zeichensatz, ausgeführt Operationen die _general_ci Sortierung verwendet werden schneller als die für die _unicode_ci Sortierungs. Zum Beispiel sind Vergleiche für die utf8_general_ci-Sortierung schneller, aber etwas weniger korrekt als Vergleiche für utf8_unicode_ci. Der Grund dafür ist, dass utf8_unicode_ci Zuordnungen wie Expansionen unterstützt; Das heißt, wenn ein Zeichen den Kombinationen anderer Zeichen gleichwertig ist. 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 ältere Sortierung, die Erweiterungen, Kontraktionen oder ignorierbare Zeichen nicht unterstützt. Es kann nur Eins-zu-Eins-Vergleiche zwischen Zeichen machen.

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

Weitere Erläuterungen finden Sie im folgenden Beitrag von MySQL-Foren lesen: http://forums.mysql.com/read.php?103,187048,188748

Was utf8_bin: Beide utf8_general_ci und utf8_unicode_ci Fall durchführen -unempfindlicher Vergleich. Im Gegensatz dazu unterscheidet utf8_bin die Groß-/Kleinschreibung (neben anderen Unterschieden), weil es die Binärwerte der Zeichen vergleicht.

+2

Ich denke, wenn du keinen guten Grund hast, _unicode_ci zu benutzen, dann benutze _general_ci. – Sagi

+4

Dies beantwortet jedoch nicht wirklich die Frage in der Tiefe. * Was ist der Unterschied zwischen diesen Kollationen genau? * –

+3

Sie haben Recht, der genaue Unterschied ist hier der Einfachheit halber nicht vorgesehen. Ich habe einen Link zu einem Post mit dem Unterschied * exact * hinzugefügt. – Sagi

82

Sie sollten sich auch der Tatsache bewusst sein, dass mit utf8_general_ci bei Verwendung eines Varchar-Feldes als eindeutiger oder primärer Index das Einfügen von 2 Werten wie "a" und "á" einen doppelten Schlüsselfehler ergibt.

+3

Danke, dies ist nützlich, um ähnliche Benutzernamen zu vermeiden (wenn beispielsweise "jose" existiert, möchte ich nicht, dass jemand anders einen "jose" -Benutzer erstellt) NB: Dies gilt auch für die meisten utf8-Sortierungen (außer utf8_bin). Das sicherste/sicherste/umfassendste ist "utf8_unicode_ci" – Costa

+2

Ich benutze utf8_bin, wo ich will, dass jose und jose im Index unterschieden werden. Zum Beispiel eine Spalte, die Such-/Ersetzungsvorgänge aufzeichnet, bei denen der Benutzer entschieden hat, nach jose zu suchen und diese durch jose zu ersetzen. (Ich schreibe ein Tabellenkalkulationsprogramm) –

6

Wirklich, ich getestet Speichern von Werten wie 'é' und 'e' in Spalte mit eindeutigen Index und sie verursachen doppelten Fehler auf beiden 'utf8_unicode_ci' und 'utf8_general_ci'. Sie können sie nur in der sortierten Spalte 'utf8_bin' speichern.

Und mysql docs (in http://dev.mysql.com/doc/refman/5.7/en/charset-applications.html) schlagen in seinen Beispielen Satz 'utf8_general_ci' Kollation vor.

[mysqld] 
character-set-server=utf8 
collation-server=utf8_general_ci 
+1

Ich habe einen schnellen Test dazu gemacht, und es scheint genau zu sein. Beide Sortierungen verhalten sich gleich, wenn es sich um einen eindeutigen Schlüssel für eine Spalte und um Werte mit Tilden und dergleichen handelt. – MirroredFate

+0

@MirroredFate OK, ich sollte hinzufügen, dass die Spalte einen eindeutigen Index haben sollte, um diesen Fehler zu verursachen. Es impliziert in meiner Antwort. – vitalii

19
  • utf8_bin vergleicht die Bits blind. Kein Fall Falten, kein Akzent Strippen.
  • utf8_general_ci vergleicht ein Byte mit einem Byte. Es tut Fall Faltung und Akzent Strippen, aber keine 2-stelligen Vergleiche: ij ist nicht gleich ij in dieser Kollation.
  • utf8_*_ci ist eine Reihe von sprachspezifischen Regeln, aber ansonsten wie unicode_ci. Einige Sonderfälle: Ç, Č, ch, ll
  • utf8_unicode_ci folgen einen alten Unicode-Standard für Vergleiche. ij = ij, aber ae! = æ
  • utf8_unicode_520_ci folgt einem neueren Unicode-Standard. ae = æ

Siehe collation chart Einzelheiten darüber, was zu dem, was in verschiedenen utf8 Sortierungen 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. Man sollte also wirklich auf utf8mb4 umsteigen, wenn man weit über Europa hinaus gehen möchte. Die obigen Punkte gelten für utf8mb4, nach entsprechender Änderung der Schreibweise. In Zukunft werden utf8mb4 und utf8mb4_unicode_520_ci bevorzugt.

  • utf16 und utf32 sind Varianten von utf8; es gibt praktisch keinen Nutzen für sie.
  • ucs2 ist näher an "Unicode" als "utf8"; es gibt praktisch keinen Nutzen dafür.
+0

Re "bleiben Sie dran": [_8.0 Kollationen_] (http://mysql.rjweb.org/utf8mb4_collations.html) zeigt, wie verschiedene Zeichen, Diphthonge usw. in den 8.0 utf8mb4 Kollationen vergleichen; utf8 ist meistens gleich. –

+0

Und 8.0 Kollatierungen werden getaktet als _significant_ schneller als 5.x. –