Quelle est la différence entre le ci général utf8 et le ci unicode utf8?

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

847
demandé sur KahWee Teng 2009-04-20 07:43:49

5 réponses

ces deux collations sont à la fois pour le codage de caractères UTF-8. Les différences résident dans la façon dont le texte est trié et comparé.

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

  • Précision

    utf8mb4_unicode_ci est basé sur le standard 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 à mettre en œuvre toutes les règles de tri Unicode, ce qui entraînera un tri indésirable dans certaines situations, comme lorsque l'on utilise des langues ou des caractères particuliers.

  • Performance

    utf8mb4_general_ci est plus rapide aux comparaisons et au tri, parce qu'il prend un tas de raccourcis liés à la performance.

    sur les serveurs modernes, cette augmentation de performance sera presque négligeable. Il a été conçu à une époque où les serveurs avaient une infime fraction de la performance CPU des ordinateurs d'aujourd'hui.

    utf8mb4_unicode_ci , qui utilise les règles Unicode pour le tri et la comparaison, emploie une assez complexe algorithme de 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 tenir compte des conventions propres à chaque langue; tout le monde ne trie pas ses caractères dans ce que nous appellerions "l'ordre alphabétique".

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

  • pour des exemples, la collation Unicode trie "ß" comme "ss", et "Œ" comme "OE" comme les personnes utilisant ces caractères le voudraient normalement, tandis que utf8mb4_general_ci les trie comme des caractères simples (probablement comme "s" et " e " respectivement).

  • certains caractères Unicode sont définis comme ignorables, ce qui signifie qu'ils ne devraient pas compter vers l'ordre de tri et la comparaison devrait passer à la le prochain personnage à la place. utf8mb4_unicode_ci les gère 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 tri simplifié utf8mb4_general_ci . La pertinence de utf8mb4_general_ci dépendra fortement de la langue utilisée. Pour certaines langues, ce sera tout à fait inadéquat.

Que devez-vous utiliser?

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

la différence de performance ne sera mesurable que dans des situations extrêmement spécialisées, et si c'est vous, vous déjà le savoir. Si vous rencontrez tri lent, dans presque tous les cas, ce sera un problème avec vos Index/Plan de requête. Changer votre fonction de collation 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 lorsque le tri précis allait être suffisamment important 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 je vais ajouter est que même si vous savez que votre application ne supporte que la langue anglaise, il peut encore avoir besoin de traiter les noms des gens, qui peuvent souvent contenir des caractères utilisés dans d'autres langues dans lesquelles il est tout aussi important de trier correctement. L'utilisation des règles Unicode pour tout permet d'ajouter la tranquillité d'esprit que les gens très intelligents Unicode ont travaillé très dur pour faire le travail de tri correctement.

1300
répondu thomasrutter 2016-09-26 05:04:36

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

j'ai créé une table très simple avec 500000 lignes:

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

puis 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

, Puis j'ai créé les procédures stockées suivantes pour référence simple SELECT, SELECT, et le tri (SÉLECTIONNEZ la COMMANDE PAR):

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 au-dessus de utf8_general_ci collation est utilisé, mais bien sûr, au cours des 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) et ensuite calculé la moyenne des valeurs.

My les résultats sont:

benchmark_simple_select () with utf8_general_ci: 9957 ms

benchmark_simple_select () with utf8_unicode_ci: 10271 ms

Dans ce benchmark, utf8_unicode_ci est plus lent que utf8_general_ci de 3,2%.

benchmark_select_like () with utf8_general_ci: 11441 ms

benchmark_select_like () with utf8_unicode_ci: 12811 ms

Dans ce benchmark, utf8_unicode_ci est plus lent que utf8_general_ci de 12%.

benchmark_order_by () with utf8_general_ci: 11944 ms

benchmark_order_by () avec utf8_unicode_ci: 12887 ms

Dans ce benchmark, utf8_unicode_ci est plus lent que utf8_general_ci de 7,9%.

130
répondu nightcoder 2017-08-06 00:03:44

Ce post décrit très bien.

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

34
répondu Michael Madsen 2010-01-01 00:31:31

voir le manuel mysql, jeux de caractères Unicode section:

pour tout jeu de caractères Unicode, les opérations effectuées à l'aide de la La collecte des données générales est plus rapide que celle des données relatives à l'unité. Par exemple, les comparaisons pour interclassement utf8_general_ci sont plus rapides, mais un peu moins correcte, que comparaisons des utf8_unicode_ci. Le la raison pour cela est que utf8_unicode_ci supporte des mappages tels que comme les expansions; c'est, quand on caractère compare égal à combinaisons d'autres caractères. Pour exemple, en allemand et quelques autres langues "ß" est égal à "ss". utf8_unicode_ci supporte aussi contractions et caractères ignorables. utf8_general_ci est un héritage de classement qui ne supporte pas les expansions, contractions, ou caractères ignorables. Il ne peut faire qu'un contre un comparaisons entre les caractères.

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 la norme entière. Le general_ci jeu sera plus rapide car il y a moins de calcul à faire.

4
répondu Dana the Sane 2009-04-20 04:09:58

en bref:

si vous avez besoin d'un meilleur tri des commandes-utilisez utf8_unicode_ci (c'est la méthode préférée),

mais si vous êtes tout à fait intéressé par la performance - utilisez utf8_general_ci , mais sachez qu'il est un peu dépassé.

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

3
répondu simhumileco 2018-03-26 08:51:49