Frage Was ist der Unterschied zwischen utf8_general_ci und utf8_unicode_ci?


Zwischen utf8_general_ci und utf8_unicode_ci, gibt es Unterschiede in Bezug auf die Leistung?


826
2018-04-20 03:43


Ursprung


Antworten:


Diese beiden Sortierfolgen sind beide für die UTF-8-Zeichencodierung. Die Unterschiede bestehen darin, wie Text sortiert und verglichen wird.

Hinweis: Seit MySQL 5.5.3 sollten Sie verwenden utf8mb4 eher, als utf8. Beide beziehen sich auf die UTF-8-Codierung, aber die ältere utf8 hatte eine MySQL-spezifische Einschränkung, die die Verwendung von Zeichen verhinderte, die über 0xFFFD nummeriert waren.

  • Richtigkeit

    utf8mb4_unicode_ci basiert auf dem Unicode-Standard zum Sortieren und Vergleichen, der in den unterschiedlichsten Sprachen genau sortiert.

    utf8mb4_general_ci Fehler beim Implementieren aller Unicode-Sortierregeln, was in einigen Situationen zu unerwünschter Sortierung führt, z. B. bei der Verwendung bestimmter Sprachen oder Zeichen.

  • Performance

    utf8mb4_general_ci ist schneller bei Vergleichen und Sortieren, weil es eine Reihe von leistungsbezogenen Verknüpfungen benötigt.

    Auf modernen Servern wird dieser Leistungsschub alles andere als vernachlässigbar sein. Es wurde zu einer Zeit entwickelt, als Server einen winzigen Bruchteil der CPU-Leistung heutiger Computer hatten.

    utf8mb4_unicode_ci, das die Unicode-Regeln zum Sortieren und Vergleichen 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 sprachspezifische Konventionen berücksichtigen. Nicht jeder sortiert seine Charaktere in einer alphabetischen Reihenfolge.

Soweit lateinische (dh "europäische") Sprachen verwendet werden, gibt es keinen großen Unterschied zwischen der Unicode-Sortierung und der vereinfachten utf8mb4_general_ci Sortierung in MySQL, aber es gibt noch ein paar Unterschiede:

  • Zum Beispiel sortiert die Unicode-Sortierung "ß" wie "ss" und "Œ" wie "OE", wie Menschen, die diese Zeichen verwenden, normalerweise wollen utf8mb4_general_ci sortiert sie als einzelne Zeichen (vermutlich wie "s" bzw. "e").

  • Einige Unicode-Zeichen sind als ignorierbar definiert, was bedeutet, dass sie nicht zur Sortierreihenfolge zählen sollten und der Vergleich stattdessen zum nächsten Zeichen gehen sollte. utf8mb4_unicode_ci Behandelt diese richtig.

In nicht-lateinischen Sprachen wie asiatischen Sprachen oder Sprachen mit unterschiedlichen Alphabeten kann es eine Menge geben Mehr Unterschiede zwischen Unicode-Sortierung und der vereinfachten utf8mb4_general_ci Sortierung. Die Eignung von utf8mb4_general_ci hängt stark von der verwendeten Sprache ab. Für einige Sprachen wird es ziemlich unzureichend sein.

Was sollten Sie verwenden?

Es gibt fast sicher keinen Grund zu verwenden utf8mb4_general_ci Wir haben den Punkt verlassen, an dem die CPU-Geschwindigkeit so niedrig ist, dass der Leistungsunterschied wichtig ist. Ihre Datenbank wird mit Sicherheit durch andere Engpässe begrenzt.

Der Unterschied in der Leistung wird nur in extrem spezialisierten Situationen messbar sein, und wenn Sie das sind, wissen Sie wahrscheinlich schon davon. Wenn Sie eine langsame Sortierung feststellen, handelt es sich in fast allen Fällen um ein Problem mit Ihren Indizes / Abfrageplänen. Das Ändern der Sortierfunktion sollte in der Liste der zu behebenden Probleme nicht hoch sein.

In der Vergangenheit haben einige Leute empfohlen zu verwenden utf8mb4_general_ci außer wenn eine genaue Sortierung wichtig genug wäre, um die Leistungskosten zu rechtfertigen. Heute sind diese Leistungskosten fast verschwunden, und Entwickler behandeln die Internationalisierung ernster.

Eine andere Sache, die ich hinzufügen werde, ist, dass, selbst wenn Sie wissen, dass Ihre Anwendung nur die englische Sprache unterstützt, es immer noch mit den Namen von Leuten zu tun haben muss, die oft Zeichen in anderen Sprachen enthalten, in denen es genauso wichtig ist, richtig zu sortieren . Wenn Sie die Unicode-Regeln für alles verwenden, können Sie beruhigt sein, dass die sehr intelligenten Unicode-Mitarbeiter sehr hart daran gearbeitet haben, die Sortierung ordnungsgemäß durchzuführen.


1267
2018-04-20 05:19



Ich wollte wissen, was der Leistungsunterschied zwischen der Verwendung von utf8_general_ci und utf8_unicode_ci ist, aber ich habe keine Benchmarks im Internet gefunden, also habe ich mich dazu entschieden, selbst Benchmarks zu erstellen.

Ich habe eine sehr einfache Tabelle mit 500000 Zeilen erstellt:

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 Ausführen dieser gespeicherten Prozedur:

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 erstellte ich die folgenden gespeicherten Prozeduren, um einfache SELECT, SELECT mit LIKE und Sortierung (SELECT mit ORDER BY) zu benchmarken:

CREATE 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

In den gespeicherten Prozeduren oben wird utf8_general_ci collation verwendet, aber natürlich habe ich während der Tests sowohl utf8_general_ci als auch utf8_unicode_ci benutzt.

Ich habe jede gespeicherte Prozedur 5 mal für jede Kollation aufgerufen (5 mal für utf8_general_ci und 5 mal für utf8_unicode_ci) und dann die Durchschnittswerte berechnet.

Meine Ergebnisse sind:

benchmark_simple_select () mit utf8_general_ci: 9957 ms
benchmark_simple_select () mit utf8_unicode_ci: 10271 ms
In diesem Benchmark ist utf8_unicode_ci um 3.2% langsamer als utf8_general_ci.

benchmark_select_like () mit utf8_general_ci: 11441 ms
benchmark_select_like () mit utf8_unicode_ci: 12811 ms
In diesem Benchmark ist utf8_unicode_ci um 12% langsamer als utf8_general_ci.

benchmark_order_by () mit utf8_general_ci: 11944 ms
benchmark_order_by () mit utf8_unicode_ci: 12887 ms
In diesem Benchmark ist utf8_unicode_ci um 7,9% langsamer als utf8_general_ci.


127
2018-03-02 02:53



Dieser Beitrag beschreibt es sehr schön.

Kurz gesagt: utf8_unicode_ci verwendet den Unicode-Sortieralgorithmus, wie er in den Unicode-Standards definiert ist, während utf8_general_ci eine einfachere Sortierreihenfolge ist, die zu "weniger genauen" Sortierergebnissen führt.


33
2018-01-01 00:31



Siehe das mysql-Handbuch, Unicode-Zeichensätze Sektion:

Für jeden Unicode-Zeichensatz   Operationen, die mit dem   _general_ci collation ist schneller als die für die _unicode_ci-Sortierung.   Zum Beispiel, Vergleiche für die   utf8_general_ci Sortierung ist schneller,   aber etwas weniger richtig, als   Vergleiche für utf8_unicode_ci. Das   Grund dafür ist das   utf8_unicode_ci unterstützt Mappings wie z   als Erweiterungen; das heißt, wenn einer   Zeichen vergleicht als gleich   Kombinationen anderer Zeichen. Zum   Beispiel, in Deutsch und einigen anderen   Sprachen "ß" ist gleich "ss".   utf8_unicode_ci unterstützt auch   Kontraktionen und ignorierbare Charaktere.   utf8_general_ci ist eine ältere Sortierung   das unterstützt keine Erweiterungen,   Kontraktionen oder ignorierbare Charaktere.   Es kann nur eins zu eins machen   Vergleiche zwischen Charakteren.

Zusammenfassend verwendet utf_general_ci eine kleinere und weniger korrekte (gemäß dem Standard) Menge von Vergleichen als utf_unicode_ci, die sollte implementieren Sie den gesamten Standard. Der set general_ci wird schneller sein, da weniger Rechenaufwand besteht.


4
2018-04-20 04:09



In kurzen Worten:

Wenn Sie eine bessere Sortierreihenfolge benötigen - verwenden Sie utf8_unicode_ci (Dies ist die bevorzugte Methode),

aber wenn Sie sich für Leistung interessieren - verwenden Sie utf8_general_ci, aber weiß, dass es ein wenig veraltet ist.

Die Unterschiede in Bezug auf die Leistung sind sehr gering.


3
2018-03-06 11:51