Was ist der Unterschied zwischen utf8_general_ci und utf8_unicode_ci
-
12-09-2019 - |
Frage
Zwischen utf8_general_ci
und utf8_unicode_ci
, gibt es Unterschiede in Bezug auf die Leistung?
Lösung
Diese beiden Sortierungen sind sowohl für die UTF-8-Zeichenkodierung. Die Unterschiede sind in, wie Text sortiert und verglichen wird.
Hinweis: Da MySQL 5.5.3 sollten Sie utf8mb4
statt utf8
. Beide beziehen sich auf die UTF-8-Codierung, aber die ältere utf8
hatte eine MySQL-spezifische Beschränkung Verwendung von Zeichen verhindert oben 0xFFFD nummeriert.
Die wichtigsten Unterschiede
-
utf8mb4_unicode_ci
ist für die universelle Sortierung und Vergleich zu den offiziellen Unicode-Regeln basieren, die genau in einer Vielzahl von Sprachen sortieren. -
utf8mb4_general_ci
ist eine vereinfachte Satz Regeln des Sortierens, die ebenso wie er kann tun soll, während viele Short-Cuts entwickelt unter Geschwindigkeit zu verbessern. Es ist nicht den Unicode-Regeln folgen und zu einem unerwünschten Sortierung oder Vergleich in einigen Situationen, wie zum Beispiel bei der Verwendung von bestimmten Sprachen oder Zeichen führen.Auf modernen Servern, wird diese Leistungssteigerung alle aber vernachlässigbar. Es wurde in einer Zeit entwickelt, als Server einen winzigen Bruchteil der CPU-Leistung heutiger Computer hatte.
Hinweis: Es existiert nun eine aktualisierte Version von utf8mb4_unicode_ci
utf8mb4_0900_ai_ci
genannt - diese basiert auf Änderungen in Unicode Version 9.0, und ist offenbar auch schneller. Es nimmt ein neues Benennungsschema wobei 0900
die Version Unicode ist und ai
bedeutet Akzent unempfindliche -. Wie der vorherige utf8mb4_unicode_ci
, Akzente in Buchstaben sind nicht signifikant angesehen
Vorteile von utf8mb4_unicode_ci
über utf8mb4_general_ci
utf8mb4_unicode_ci
, die 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 wenn eine große Auswahl an Sonderzeichen verwenden. Diese Regeln müssen Berücksichtigung sprachspezifische Konventionen zu übernehmen; nicht alle sortiert ihre Charaktere in dem, was wir ‚alphabetischer Reihenfolge.‘
Was Latein (dh „europäische“) Sprachen gehen, gibt es nicht viel Unterschied zwischen dem Unicode ist das Sortieren und die vereinfachte utf8mb4_general_ci
in MySQL Sortierung, aber es gibt noch ein paar Unterschiede:
-
Für die Beispiele, die Unicode-Sortier Sorten „ß“ wie „ss“ und „oe“ wie „OE“, wie Leute, die diese Zeichen verwenden normalerweise wollen würde, während
utf8mb4_general_ci
sie als einzelne Zeichen sortiert (vermutlich wie „s "und "e" bezeichnet). -
Einige Unicode-Zeichen werden als ignorable definiert, das heißt, sie nicht auf die Sortierreihenfolge und der Vergleich sollte stattdessen auf das nächste Zeichen bewegen sich verlassen sollte.
utf8mb4_unicode_ci
behandelt diese richtig.
In nicht-lateinischen Sprachen wie asiatische Sprachen oder Sprachen mit verschiedenen Alphabeten, kann es eine Menge mehr Unterschiede zwischen Unicode-Sortierung und der vereinfachten utf8mb4_general_ci
Sortierung sein. Die Eignung der utf8mb4_general_ci
hängt stark von der verwendeten Sprache. Für einige Sprachen, wird es völlig unzureichend sein.
Was sollten Sie verwenden?
Es ist mit ziemlicher Sicherheit kein Grund mehr zu verwenden utf8mb4_general_ci
, wie wir hinter dem Punkt verlassen haben, wo die CPU-Geschwindigkeit niedrig genug ist, dass der Unterschied in der Leistung wichtig sein würde. Ihre Datenbank wird mit ziemlicher Sicherheit durch andere Engpässe als diese begrenzt werden.
In der Vergangenheit empfohlen einige Leute utf8mb4_general_ci
außer zu verwenden, wenn eine genaue Sortierung wichtig genug sein würde, die Leistung Kosten zu rechtfertigen. Heute ist diese Leistung gekostet hat so gut wie verschwunden, und Entwickler behandeln Internationalisierung mehr ernst.
Es gibt ein Argument gemacht werden, dass, wenn die Geschwindigkeit als die Genauigkeit ist Ihnen wichtiger ist, können Sie auch keine Sortierung bei allen Produkten. Es ist trivial ein machenAlgorithmus schneller, wenn Sie brauchen es nicht genau. So utf8mb4_general_ci
ist ein Kompromiss, der wahrscheinlich nicht aus Geschwindigkeitsgründen erforderlich und wahrscheinlich auch nicht geeignet für die Richtigkeit Gründe.
Eine andere Sache, die ich hinzufügen, ist, dass selbst wenn Sie Ihre Anwendung kennen nur die englische Sprache unterstützt, kann es nach wie vor mit Personennamen befassen muß, die oft Zeichen in anderen Sprachen verwendet werden, enthalten können, in denen es genauso wichtig ist, richtig zu sortieren. hilft unter Verwendung der Unicode-Regeln für allen Seelenfrieden hinzufügen, dass die sehr intelligenten Unicode Menschen Arbeit richtig zu machen Sortierung sehr hart gearbeitet haben, zu.
Was die Teile bedeuten
Zum einen ci
ist für Groß- und Kleinschreibung Sortieren und Vergleich. Dies bedeutet, es für Textdaten geeignet ist, und Fall ist nicht wichtig. Die anderen Typen von Sortier sind cs
(Groß-) für Textdaten in dem Fall wichtig ist, und bin
, denn wo die Codierung Bedürfnisse anzupassen, Bit für Bit, die für Felder geeignet ist, die wirklich binäre Daten (einschließlich codiert sind, für Beispiel Base64). Case-sensitive Sortierung führt zu einigen seltsamen Resultaten und case-sensitive Vergleich kann in doppelte Werte ergeben sich nur in Groß- und Kleinschreibung, so Groß- und Sortierungen fallen aus Bevorzugung für Textdaten - wenn Fall zu Ihnen wichtig ist, dann sonst ignorable Interpunktion und so weiter ist wahrscheinlich auch signifikant, und eine binäre Sortierung könnte besser geeignet sein.
Als nächstes unicode
oder general
bezieht sich auf die spezifischen Sortier- und Vergleichsregeln - insbesondere die Art und Weise Text normiert oder verglichen. Es gibt viele verschiedene Arten von Regeln für die utf8mb4 Zeichencodierung, mit unicode
und general
zwei zu sein, die in allen möglichen Sprachen statt einem spezifischen zu arbeiten gut versuchen. Die Unterschiede zwischen diesen beiden Regelungen sind Gegenstand dieser Antwort. Beachten Sie, dass neuere Regelsätze 0900
umfassen unter Bezugnahme auf Unicode 9.0 und unicode_520
auf Unicode 5.2 Bezug genommen wird.
Und schließlich ist utf8mb4
natürlich die Zeichenkodierung intern verwendet. In dieser Antwort spreche ich nur über Unicode basierte Kodierungen.
Andere Tipps
wollte ich wissen, was der Performance-Unterschied ist utf8_general_ci
und utf8_unicode_ci
zwischen der Verwendung, aber ich habe kein Benchmarks im Internet aufgelistet, so habe ich beschlossen, Benchmarks selbst zu erstellen.
Ich habe eine sehr einfache Tabelle mit 500.000 Zeilen:
CREATE TABLE test(
ID INT(11) DEFAULT NULL,
Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;
Dann füllte ich es mit zufälligen Daten durch diese gespeicherte Prozedur ausgeführt wird:
CREATE PROCEDURE randomizer()
BEGIN
DECLARE i INT DEFAULT 0;
DECLARE random CHAR(20) ;
theloop: loop
SET random = CONV(FLOOR(RAND() * 99999999999999), 20, 36);
INSERT INTO test VALUES (i+1, random);
SET i=i+1;
IF i = 500000 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END
Dann habe ich die folgenden gespeicherten Prozeduren zur Benchmark einfachen SELECT
, SELECT
mit LIKE
und Sortieren (SELECT
mit ORDER BY
):
CREATE PROCEDURE benchmark_simple_select()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE Description = 'test' COLLATE utf8_general_ci;
SET i = i + 1;
IF i = 30 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
CREATE PROCEDURE benchmark_select_like()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE Description LIKE '%test' COLLATE utf8_general_ci;
SET i = i + 1;
IF i = 30 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
CREATE PROCEDURE benchmark_order_by()
BEGIN
DECLARE i INT DEFAULT 0;
theloop: loop
SELECT *
FROM test
WHERE ID > FLOOR(1 + RAND() * (400000 - 1))
ORDER BY Description COLLATE utf8_general_ci LIMIT 1000;
SET i = i + 1;
IF i = 10 THEN
LEAVE theloop;
END IF;
END LOOP theloop;
END;
Bei den gespeicherten Prozeduren über utf8_general_ci
Kollatierung verwendet wird, aber natürlich bei den Tests verwendete ich sowohl utf8_general_ci
und utf8_unicode_ci
.
rief ich jede gespeicherte Prozedur 5 mal für jeden Vergleich (5-mal für utf8_general_ci
und 5-mal für utf8_unicode_ci
) und dann die Mittelwert berechnet.
Meine Ergebnisse sind:
benchmark_simple_select()
- mit
utf8_general_ci
: 9957 ms - mit
utf8_unicode_ci
: 10.271 ms
In dieser Benchmark mit utf8_unicode_ci
langsamer als utf8_general_ci
um 3,2%.
benchmark_select_like()
- mit
utf8_general_ci
: 11.441 ms - mit
utf8_unicode_ci
: 12.811 ms
In dieser Benchmark mit utf8_unicode_ci
ist langsamer als utf8_general_ci
um 12%.
benchmark_order_by()
- mit
utf8_general_ci
: 11.944 ms - mit
utf8_unicode_ci
: 12.887 ms
In dieser Benchmark mit utf8_unicode_ci
langsamer als utf8_general_ci
um 7,9%.
Dieser Beitrag es beschreibt sehr schön.
Kurz gesagt:. Utf8_unicode_ci verwendet den Unicode Kollatierungsalgorithmus wie in den Unicode-Standards definiert, während utf8_general_ci eine einfache Sortierreihenfolge, die in „ungenauen“ Sortierergebnissen
Sehen Sie das MySQL-Handbuch, Unicode-Zeichensätze Abschnitt:
Für alle Unicode-Zeichensatz, Operationen durchgeführt die Verwendung von _general_ci Sortierungs sind schneller als die für die _unicode_ci Sortierung. Zum Beispiel Vergleiche für die utf8_general_ci Sortierungs sind schneller, aber etwas weniger korrekt, als Vergleiche für utf8_unicode_ci. Das Grund dafür ist, dass utf8_unicode_ci unterstützt Mappings solchen als Erweiterungen; das heißt, wenn man Zeichen vergleicht als gleich Kombinationen von anderen Zeichen. Zum zB in der deutschen und einige andere Sprachen „ß“ ist gleich „ss“. utf8_unicode_ci unterstützt auch Kontraktionen und vernachlässigbares Zeichen. utf8_general_ci ist ein Vermächtnis Sortierungs dass keine Unterstützung für Erweiterungen, Kontraktionen oder ignorable Zeichen. Es kann nur eins-zu-eins machen zwischen den Zeichen Vergleiche.
Um es zusammenzufassen, utf_general_ci verwendet eine kleinere und weniger korrekt ist (nach der Norm) Satz von Vergleichen als utf_unicode_ci die sollte die gesamte Standard implementieren. Die general_ci Set wird schneller sein, weil es weniger Berechnung zu tun.
Kurz Worten:
Wenn Sie besser brauchen Sortierreihenfolge - Verwendung utf8_unicode_ci
(dies ist die bevorzugte Methode),
aber wenn man ganz interessiert an Leistung -. Verwendung utf8_general_ci
, aber weiß, dass es ein wenig veraltet ist
Die Unterschiede in Bezug auf die Leistung sehr gering sind.
Einige Details (PL)
Wie können wir eine href lesen <= "https://bugs.mysql.com/bug.php?id=9604%20%E2%80%93%20user3399549%20Mar%209%20%2714%20at% 2021: 15" rel = "nofollow noreferrer"> hier ( Peter Gulutzan ) gibt es Unterschiede auf Sortieranlagen / Vergleich polish Buchstaben "L" (L mit Schlaganfall - html esc: Ł
) ( Kleinbuchstaben: "L" - html esc: ł
) - haben wir folgende Annahme:
utf8_polish_ci Ł greater than L and less than M
utf8_unicode_ci Ł greater than L and less than M
utf8_unicode_520_ci Ł equal to L
utf8_general_ci Ł greater than Z
In polnischer Sprache Brief Ł
ist nach Brief L
und vor M
. Keiner dieser Codierung ist besser oder schlechter - es Ihre Bedürfnisse ab.