Gibt es zwischen utf8_general_ci
und utf8_unicode_ci
irgendwelche Unterschiede in Bezug auf die Leistung?
Diese beiden Sortierungen sind beide für die UTF-8-Zeichenkodierung. Die Unterschiede liegen darin, wie der Text sortiert und verglichen wird.
Hinweis: Sie sollten utf8mb4
und nicht utf8
verwenden. Beide beziehen sich auf die UTF-8-Kodierung, aber das ältere utf8
hatte eine MySQL-spezifische Einschränkung, die die Verwendung von Zeichen mit einer Nummer über 0xFFFD verhindert.
Hinweis: Neuere Versionen von MySQL haben aktualisierte Unicode-Sortierregeln, die unter Namen wie utf8mb4_0900_ci
für Regeln verfügbar sind, die auf Unicode 9.0 basieren - und keine gleichwertige general
-Variante haben.
Schlüsselunterschiede
utf8mb4_unicode_ci
basiert auf den offiziellen Unicode-Regeln für universelles Sortieren und Vergleichen, die in einer Vielzahl von Sprachen genau sortieren.
Er folgt nicht den Unicode-Regeln und wird in einigen Situationen zu unerwünschten Sortierungen oder Vergleichen führen, z.B. bei der Verwendung bestimmter Sprachen oder Zeichen.
Auf modernen Servern ist dieser Leistungszuwachs so gut wie vernachlässigbar. Sie wurde in einer Zeit entwickelt, als Server nur einen winzigen Bruchteil der CPU-Leistung heutiger Computer hatten.
*Hinweis: Es gibt jetzt eine aktualisierte Version von utf8mb4_unicode_ci
mit dem Namen utf8mb4_0900_ai_ci
- diese basiert auf Änderungen in der Unicode-Version 9.0 und ist offensichtlich auch schneller. Es nimmt ein neues Namensschema an, wobei 0900
die Unicode-Version ist und ai
akzentunempfindlich bedeutet - wie das vorherige utf8mb4_unicode_ci
werden Akzente in Buchstaben nicht als signifikant angesehen.
Vorteile von utf8mb4_unicode_ci
gegenüber utf8mb4_general_ci
Das Programm utf8mb4_unicode_ci
, das die Unicode-Regeln für die Sortierung und den Vergleich verwendet, verwendet einen ziemlich komplexen Algorithmus für die korrekte Sortierung in einer Vielzahl von Sprachen und bei Verwendung einer Vielzahl von Sonderzeichen. Diese Regeln müssen die sprachspezifischen Konventionen berücksichtigen; nicht jeder sortiert seine Zeichen in dem, was wir als "alphabetische Reihenfolge" bezeichnen würden.
Was die lateinischen (d.h. "europäischen") Sprachen betrifft, gibt es keinen großen Unterschied zwischen der Unicode-Sortierung und der vereinfachten utf8mb4_general_ci
-Sortierung in MySQL, aber es gibt dennoch ein paar Unterschiede:utf8mb4_general_ci
sie als einzelne Zeichen sortiert (vermutlich wie "s" bzw. "e").utf8mb4_unicode_ci
behandelt diese richtig.
In nicht-lateinischen Sprachen, wie z.B. asiatischen Sprachen oder Sprachen mit anderen Alphabeten, kann es viel mehr Unterschiede zwischen der Unicode-Sortierung und der vereinfachten utf8mb4_general_ci
-Sortierung geben. Die Eignung von utf8mb4_general_ci
wird stark von der verwendeten Sprache abhängen. Für einige Sprachen wird es ziemlich unzureichend sein.
Was sollten Sie verwenden?
Es gibt mit ziemlicher Sicherheit keinen Grund mehr, utf8mb4_general_ci
zu verwenden, da wir den Punkt hinter uns gelassen haben, an dem die CPU-Geschwindigkeit niedrig genug ist, dass der Leistungsunterschied von Bedeutung wäre. Ihre Datenbank wird mit ziemlicher Sicherheit durch andere Engpässe als diesen begrenzt sein.
In der Vergangenheit haben einige Leute empfohlen, utf8mb4_general_ci
zu verwenden, es sei denn, eine genaue Sortierung war wichtig genug, um die Leistungskosten zu rechtfertigen. Heute sind diese Leistungskosten so gut wie verschwunden, und die Entwickler nehmen die Internationalisierung immer ernster.
Man kann argumentieren, dass, wenn Geschwindigkeit wichtiger ist als Genauigkeit, man genauso gut überhaupt keine Sortierung vornehmen kann. Es ist trivial, einen Algorithmus schneller zu machen, wenn er nicht genau sein muss. Daher ist "utf8mb4_general_ci" ein Kompromiss, der wahrscheinlich aus Geschwindigkeitsgründen nicht benötigt wird und wahrscheinlich auch aus Gründen der Genauigkeit nicht geeignet ist.
Eine weitere Sache, die ich hinzufügen möchte, ist, dass, selbst wenn Sie wissen, dass Ihre Anwendung nur die englische Sprache unterstützt, sie dennoch mit den Namen von Personen umgehen muss, die oft Zeichen enthalten können, die in anderen Sprachen verwendet werden, bei denen es genauso wichtig ist, sie korrekt zu sortieren. Wenn Sie die Unicode-Regeln für alles verwenden, können Sie sich darauf verlassen, dass die klugen Unicode-Mitarbeiter sehr hart daran gearbeitet haben, dass die Sortierung richtig funktioniert.
Was die Teile bedeuten
Erstens ist "ci" für das Sortieren und Vergleichen ohne Berücksichtigung der Groß-/Kleinschreibung gedacht. Das bedeutet, dass es für Textdaten geeignet ist und die Groß-/Kleinschreibung nicht wichtig ist. Die anderen Sortierarten sind "cs" (Groß-/Kleinschreibung) für Textdaten, bei denen die Groß-/Kleinschreibung wichtig ist, und "bin", wenn die Kodierung Bit für Bit übereinstimmen muss, was für Felder geeignet ist, bei denen es sich wirklich um kodierte Binärdaten handelt (einschließlich z. B. Base64). Die Sortierung unter Berücksichtigung der Groß- und Kleinschreibung führt zu einigen seltsamen Ergebnissen und der Vergleich unter Berücksichtigung der Groß- und Kleinschreibung kann zu doppelten Werten führen, die sich nur in der Groß- und Kleinschreibung unterscheiden, so dass die Sortierung unter Berücksichtigung der Groß- und Kleinschreibung für Textdaten an Bedeutung verliert - wenn die Groß- und Kleinschreibung für Sie von Bedeutung ist, dann ist die ansonsten ignorierbare Interpunktion usw. wahrscheinlich auch von Bedeutung und eine binäre Sortierung könnte angemessener sein.
Als nächstes bezieht sich "Unicode" oder "Allgemein" auf die spezifischen Sortier- und Vergleichsregeln - insbesondere auf die Art und Weise, wie Text normalisiert oder verglichen wird. Es gibt viele verschiedene Regelsätze für die utf8mb4-Zeichenkodierung, wobei unicode
und general
zwei sind, die versuchen, in allen möglichen Sprachen gut zu funktionieren und nicht nur in einer bestimmten Sprache. Die Unterschiede zwischen diesen beiden Regelwerken sind das Thema dieser Antwort. Beachten Sie, dass unicode
die Regeln von Unicode 4.0 benutzt. Neuere Versionen von MySQL fügen die Regelsätze unicode_520
hinzu, die Regeln aus Unicode 5.2 verwenden, und 0900
(ohne den "unicode_"-Teil), der Regeln aus Unicode 9.0 verwendet.
Und schließlich ist utf8mb4
natürlich die intern verwendete Zeichenkodierung. In dieser Antwort spreche ich nur über Unicode-basierte Kodierungen.Siehe das mysql-Handbuch, Abschnitt Unicode-Zeichensätze:
Für jeden Unicode-Zeichensatz, Operationen, die mit der _general_ci Kollation durchgeführt werden, schneller als die für die _unicode_ci Kollation. Zum Beispiel, Vergleiche für den utf8_general_ci-Kollation schneller, aber etwas weniger korrekt, als Vergleiche für utf8_unicode_ci. Der Grund dafür ist, dass utf8_unicode_ci unterstützt Mappings wie wie Expansionen; das heißt, wenn ein Zeichen als gleichwertig verglichen wird mit Kombinationen von anderen Zeichen. Für Beispiel: Im Deutschen und einigen anderen Sprachen ist "ß" gleich "ss". utf8_unicode_ci unterstützt auch Kontraktionen und ignorierbare Zeichen. utf8_general_ci ist eine Legacy-Kollation die keine Expansionen unterstützt, Kontraktionen oder ignorierbare Zeichen unterstützt. Sie kann nur Eins-zu-Eins Vergleiche zwischen Zeichen durchführen.
Zusammenfassend lässt sich also sagen, dass utf_general_ci einen kleineren und weniger korrekten (gemäß der Norm) Satz von Vergleichen verwendet als utf_unicode_ci, das die gesamte Norm implementieren sollte. Der general_ci-Satz wird schneller sein, weil weniger Berechnungen durchgeführt werden müssen.