Question

Entre utf8_general_ci et utf8_unicode_ci, y at-il des différences en termes de performance?

Était-ce utile?

La solution

Ces deux sont à la fois pour les classements du caractère encodage UTF-8. Les différences sont dans la façon dont le texte est trié et comparé.

Note: Depuis MySQL 5.5.3 devrait utiliser utf8mb4 plutôt que utf8. Ils se réfèrent tous deux à l'encodage UTF-8, mais le plus utf8 avait une limitation spécifique à MySQL empêcher l'utilisation de caractères numérotés ci-dessus 0xFFFD.

Les principales différences

  • utf8mb4_unicode_ci est basé sur les règles Unicode officielles pour le tri universel et la comparaison, qui trie avec précision dans un large éventail de langues.

  • utf8mb4_general_ci est un ensemble simplifié de règles de tri qui vise à faire aussi bien que possible tout en prenant de nombreux raccourcis conçus pour améliorer la vitesse. Il ne suit pas les règles Unicode et se traduira par le tri ou la comparaison indésirable dans certaines situations, comme lors de l'utilisation des langues particulières ou des caractères.

    Sur les serveurs modernes, ce gain de performance sera tout sauf négligeable. Il a été conçu à une époque où les serveurs avaient une petite fraction de la performance du processeur des ordinateurs d'aujourd'hui.

Remarque: il existe maintenant une version mise à jour de utf8mb4_unicode_ci appelé utf8mb4_0900_ai_ci - ceci est basé sur les changements dans la version Unicode 9.0, et est aussi apparemment plus rapide. Il adopte un nouveau schéma de nommage dans lequel 0900 est la version Unicode et ai signifie accent insensible à la casse -. Comme le utf8mb4_unicode_ci précédent, les accents dans les lettres ne sont pas considérées comme significatives

Avantages de utf8mb4_unicode_ci sur utf8mb4_general_ci

utf8mb4_unicode_ci, qui utilise les règles Unicode pour le tri et la comparaison, emploie un algorithme assez complexe pour le tri correct dans un large éventail de langues et l'utilisation d'un large éventail de caractères spéciaux. Ces règles doivent tenir compte des conventions spécifiques à la langue; pas tout le monde trie leurs personnages dans ce que nous appelons «l'ordre alphabétique.

En ce qui concerne le latin (ie « européenne ») langues vont, il n'y a pas beaucoup de différence entre le tri Unicode et le utf8mb4_general_ci simplifié le tri dans MySQL, mais il y a encore quelques différences:

  • Pour des exemples, les types de classement Unicode « ß » comme « ss » et « Œ » comme « OE » que les personnes utilisant ces caractères normalement veulent, alors que utf8mb4_general_ci les trie comme un seul caractère (probablement comme « s "et "e" respectivement).

  • Certains caractères Unicode sont définis comme ignorable, ce qui signifie qu'ils ne devraient pas compter dans l'ordre de tri et la comparaison devrait passer au caractère suivant à la place. utf8mb4_unicode_ci gère ces correctement.

Dans les langues non latines, comme les langues asiatiques ou langues avec des alphabets différents, il peut y avoir beaucoup plus différences entre Unicode tri et le tri utf8mb4_general_ci simplifié. La pertinence de utf8mb4_general_ci dépendra en grande partie de la langue utilisée. Pour certaines langues, ce sera tout à fait insuffisant.

Que faut-il utiliser?

Il n'y a certainement aucune raison d'utiliser utf8mb4_general_ci plus, comme nous l'avons laissé derrière le point où la vitesse du processeur est suffisamment faible pour que la différence de performance serait important. Votre base de données sera presque certainement limitée par d'autres goulots d'étranglement que cela.

Dans le passé, certaines personnes recommandé d'utiliser utf8mb4_general_ci sauf si le tri précis allait être suffisamment important pour justifier le coût de la performance. Aujourd'hui, que le coût de la performance a pratiquement disparu, et les développeurs sont l'internationalisation traite plus sérieusement.

Il y a un argument à faire que si la vitesse est plus important pour vous que la précision, vous pouvez aussi bien faire aucun tri ne pas du tout. Il est trivial de faire unalgorithme plus rapide si vous ne avez pas besoin d'être précis. Ainsi, utf8mb4_general_ci est un compromis qui est probablement pas nécessaire pour des raisons de vitesse et probablement ne convient pas pour des raisons de précision.

Une autre chose que je vais ajouter est que même si vous savez que votre application prend en charge que la langue anglaise, il peut encore avoir besoin de traiter les noms des personnes, qui peuvent contenir souvent des caractères utilisés dans d'autres langues dans lesquelles il est tout aussi important pour trier correctement. En utilisant les règles Unicode pour tout aide ajouter la tranquillité d'esprit que les gens très intelligents Unicode ont travaillé très dur pour faire fonctionner le tri correctement.

Qu'est-ce que les parties signifient

Tout d'abord, ci est pour insensible à la casse de tri et de comparaison. Cela signifie qu'il est approprié pour les données textuelles, et le cas est pas important. Les autres types de collation sont cs (sensible à la casse) pour les données textuelles où le cas est important, et bin, pour lequel le codage doit correspondre, peu à peu, ce qui convient pour les champs qui sont vraiment données binaires codées (y compris, pour par exemple, base64). tri-sensible à la casse conduit à des résultats étranges et comparaison sensible à la casse peut entraîner des valeurs en double ne diffèrent que dans la lettre cas, si les classements sensibles à la casse sont en baisse de faveur pour les données textuelles - si le cas est important pour vous, sinon la ponctuation ignorable et ainsi de suite est probablement aussi important, et un classement binaire pourrait être plus approprié.

Ensuite, unicode ou general fait référence au tri et règles comparaison - en particulier, le texte de façon normalisée est ou par rapport. Il existe de nombreux ensembles de règles différentes pour le caractère utf8mb4 encodage, avec unicode et general étant deux qui tentent de bien travailler dans toutes les langues possibles plutôt que spécifique. Les différences entre ces deux ensembles de règles font l'objet de cette réponse. Notez que les ensembles de règles plus récentes comprennent 0900 se référant à Unicode 9.0, et se référant à unicode_520 Unicode 5.2.

Enfin, utf8mb4 est bien sûr le codage des caractères utilisé en interne. Dans cette réponse, je ne parle que encodages Unicode base.

Autres conseils

Je voulais savoir quelle est la différence de performance entre l'utilisation utf8_general_ci et utf8_unicode_ci, mais je ne trouve pas de points de repère figurant sur Internet, alors j'ai décidé de créer moi-même des repères.

Je créé une table très simple avec 500.000 lignes:

CREATE TABLE test(
  ID INT(11) DEFAULT NULL,
  Description VARCHAR(20) DEFAULT NULL
)
ENGINE = INNODB
CHARACTER SET utf8
COLLATE utf8_general_ci;

Ensuite, je l'ai rempli avec des données aléatoires en exécutant cette procédure stockée:

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

Ensuite, j'ai créé les procédures stockées suivantes pour SELECT simples de référence, SELECT avec LIKE, et le tri (SELECT avec 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;

Dans les procédures stockées ci-dessus classement utf8_general_ci est utilisé, mais bien sûr, au cours des tests que j'utilisé à la fois utf8_general_ci et utf8_unicode_ci.

I appelé chaque procédure stockée 5 fois pour chaque assemblage (5 fois pour utf8_general_ci et 5 fois pour utf8_unicode_ci) et ensuite calculé les valeurs moyennes.

Mes résultats sont les suivants:

benchmark_simple_select()

  • avec utf8_general_ci: 9,957 ms
  • avec utf8_unicode_ci: 10,271 ms

Dans cet indice de référence en utilisant utf8_unicode_ci est plus lent que utf8_general_ci de 3,2%.

benchmark_select_like()

  • avec utf8_general_ci: 11,441 ms
  • avec utf8_unicode_ci: 12,811 ms

Dans cet indice de référence en utilisant utf8_unicode_ci est plus lent que utf8_general_ci de 12%.

benchmark_order_by()

  • avec utf8_general_ci: 11,944 ms
  • avec utf8_unicode_ci: 12,887 ms

Dans cet indice de référence en utilisant utf8_unicode_ci est plus lent que utf8_general_ci de 7,9%.

Cette post décrit très bien.

En bref:. Utf8_unicode_ci utilise Unicode Collation algorithme tel que défini dans les normes Unicode, alors que utf8_general_ci est un ordre de tri plus simple qui se traduit par « moins précis » des résultats de tri

Voir le manuel de MySQL, jeux de caractères Unicode section:

  

Pour tout jeu de caractères Unicode,   les opérations effectuées en utilisant le   collation _general_ci sont plus rapides que ceux de la collation _unicode_ci.   Par exemple, les comparaisons pour le   collation utf8_general_ci sont plus rapides,   mais un peu moins bonne, que   des comparaisons pour utf8_unicode_ci. le   la raison en est que   utf8_unicode_ci prend en charge ces mappages   comme l'expansion; qui est, quand une   caractère compare égal à   combinaisons d'autres caractères. Pour   par exemple, en allemand et quelques autres   langues « ß » est égal à « ss ».   utf8_unicode_ci soutient également   contractions et caractères ignorable.   utf8_general_ci est un classement héritage   qui ne prend pas en charge l'expansion,   contractions ou des caractères ignorable.   Il peut faire qu'une seule à un   les comparaisons entre les caractères.

Donc, pour résumer, utf_general_ci utilise un ensemble de comparaisons que utf_unicode_ci qui devraient mettre en œuvre toute la norme plus petite et moins correcte (selon la norme). L'ensemble sera plus rapide general_ci parce qu'il ya moins de calculs à faire.

En bref mots:

Si vous avez besoin de mieux l'ordre de tri - utilisation utf8_unicode_ci (ce qui est la méthode préférée),

mais si vous tout à fait intéressé par la performance -. utf8_general_ci utilisation, mais sachez qu'il est un peu obsolète

Les différences en termes de performance sont très faibles.

Quelques détails (PL)

Comme on peut le lire ici ( Peter Gulutzan ) il y a une différence sur le tri / comparer lettre polonaise "L" (L avec course - html esc: Ł) ( minuscule: "L" - html esc: ł) - nous avons hypothèse ci-dessous:

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

Dans la lettre de langue polonaise est Ł après lettre L et avant M. Aucun de ce codage est meilleur ou pire - cela dépend de vos besoins.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top