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?
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.
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%.
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".
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.
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.