Question Quelle est la différence entre utf8_general_ci et utf8_unicode_ci


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


826
2018-04-20 03:43


origine


Réponses:


Ces deux classements sont tous les deux pour le codage de caractères UTF-8. Les différences sont dans la façon dont le texte est trié et comparé.

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

  • Précision

    utf8mb4_unicode_ci est basé sur la norme Unicode pour le tri et la comparaison, qui trie avec précision dans un très large éventail de langues.

    utf8mb4_general_ci ne parvient pas à implémenter toutes les règles de tri Unicode, ce qui entraînera un tri indésirable dans certaines situations, comme lors de l'utilisation de langues ou de caractères particuliers.

  • Performance

    utf8mb4_general_ci est plus rapide dans les comparaisons et le tri, car il faut un certain nombre de raccourcis liés aux performances.

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

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

En ce qui concerne les langues latines ("européennes"), il n'y a pas beaucoup de différence entre le tri Unicode et le utf8mb4_general_ci le tri en MySQL, mais il y a encore quelques différences:

  • Par exemple, le classement Unicode trie "ß" comme "ss", et "Œ" comme "OE" comme les gens qui utilisent ces caractères voudraient normalement, alors que utf8mb4_general_ci les trie en tant que caractères simples (vraisemblablement comme "s" et "e" respectivement).

  • Certains caractères Unicode sont définis comme ignorables, ce qui signifie qu'ils ne doivent pas être pris en compte dans l'ordre de tri et que la comparaison doit passer au caractère suivant. utf8mb4_unicode_ci les manipule correctement.

Dans les langues non latines, telles que les langues asiatiques ou les langues avec des alphabets différents, il peut y avoir beaucoup plus différences entre le tri Unicode et le simplifié utf8mb4_general_ci tri. La pertinence de utf8mb4_general_ci dépendra fortement de la langue utilisée. Pour certaines langues, ce sera très insuffisant.

Que devriez-vous utiliser?

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

La différence de performance ne sera mesurable que dans des situations extrêmement spécialisées, et si c'est vous, vous le savez probablement déjà. Si vous rencontrez un problème de tri, dans la plupart des cas, il y aura un problème avec vos index / plan de requête. Changer votre fonction de classement ne devrait pas être en haut de la liste des choses à dépanner.

Dans le passé, certaines personnes ont recommandé d'utiliser utf8mb4_general_ci sauf quand un tri précis serait suffisant pour justifier le coût de la performance. Aujourd'hui, ce coût de performance a pratiquement disparu et les développeurs traitent l'internationalisation plus sérieusement.

Une autre chose que j'ajouterai est que même si vous savez que votre application ne supporte que l'anglais, elle peut toujours avoir besoin de gérer les noms des personnes, qui peuvent souvent contenir des caractères utilisés dans d'autres langues dans lesquelles il est important de trier correctement . L'utilisation des règles Unicode pour tout contribue à la tranquillité d'esprit que les personnes très intelligentes d'Unicode ont travaillé très dur pour que le tri fonctionne correctement.


1267
2018-04-20 05:19



Je voulais savoir quelle est la différence de performance entre utf8_general_ci et utf8_unicode_ci, mais je n'ai trouvé aucun benchmark sur Internet, j'ai donc décidé de créer moi-même des benchmarks.

J'ai 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 référencer SELECT simple, SELECT avec LIKE et tri (SELECT avec ORDER BY):

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

Dans les procédures stockées ci-dessus utf8_general_ci collation est utilisé, mais bien sûr pendant les tests j'ai utilisé à la fois utf8_general_ci et utf8_unicode_ci.

J'ai appelé chaque procédure stockée 5 fois pour chaque classement (5 fois pour utf8_general_ci et 5 fois pour utf8_unicode_ci) puis j'ai calculé les valeurs moyennes.

Mes résultats sont:

benchmark_simple_select () avec utf8_general_ci: 9957 ms
benchmark_simple_select () avec utf8_unicode_ci: 10271 ms
Dans ce cas-test, utf8_unicode_ci est plus lent que utf8_general_ci de 3,2%.

benchmark_select_like () avec utf8_general_ci: 11441 ms
benchmark_select_like () avec utf8_unicode_ci: 12811 ms
Dans ce cas-test, utf8_unicode_ci est plus lent que utf8_general_ci de 12%.

benchmark_order_by () avec utf8_general_ci: 11944 ms
benchmark_order_by () avec utf8_unicode_ci: 12887 ms
Dans ce cas-test, utf8_unicode_ci est plus lent que utf8_general_ci de 7,9%.


127
2018-03-02 02:53



Ce post le décrit très bien.

En bref: utf8_unicode_ci utilise l'algorithme Unicode Collation tel que défini dans les standards Unicode, alors que utf8_general_ci est un ordre de tri plus simple qui donne des résultats de tri "moins précis".


33
2018-01-01 00:31



Voir le manuel de mysql, Ensembles de caractères Unicode section:

Pour tout jeu de caractères Unicode,   opérations effectuées en utilisant le   Les collations _general_ci sont plus rapides que celles de la collation _unicode_ci.   Par exemple, des comparaisons pour   utf8_general_ci collation sont plus rapides,   mais légèrement moins correct que   comparaisons pour utf8_unicode_ci. le   raison pour cela est que   utf8_unicode_ci prend en charge les mappages tels   comme expansions; c'est quand un   personnage compare égal à   combinaisons d'autres caractères. Pour   exemple, en allemand et d'autres   langues "ß" est égal à "ss".   utf8_unicode_ci prend également en charge   contractions et caractères ignorables.   utf8_general_ci est une collation héritée   cela ne supporte pas les expansions,   contractions ou caractères ignorables.   Il peut faire seulement one-to-one   comparaisons entre les caractères.

Donc, pour résumer, utf_general_ci utilise un ensemble de comparaisons plus petit et moins correct (selon la norme) que utf_unicode_ci qui devrait mettre en œuvre l'ensemble de la norme. L'ensemble general_ci sera plus rapide car il y a moins de calculs à faire.


4
2018-04-20 04:09



En quelques mots:

Si vous avez besoin d'un meilleur ordre de tri - utilisation utf8_unicode_ci (c'est la méthode préférée),

mais si vous êtes totalement intéressé par la performance - utilisation utf8_general_ci, mais sachez que c'est un peu démodé.

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


3
2018-03-06 11:51