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 sur Internet, alors j'ai décidé de faire des benchmarks moi-même.
J'ai créé un tableau très simple de 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;
Puis je l'ai rempli de 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
J'ai ensuite créé les procédures stockées suivantes pour effectuer des tests de référence (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, la collation utf8_general_ci est utilisée, 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 collation (5 fois pour utf8_general_ci et 5 fois pour utf8_unicode_ci) et j'ai ensuite calculé les valeurs moyennes.
Voici les résultats :
benchmark_simple_select() avec utf8_general_ci : 9957 ms
benchmark_simple_select() avec utf8_unicode_ci : 10271 ms
Dans ce benchmark, l'utilisation de utf8_unicode_ci est plus lente 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 benchmark, l'utilisation de utf8_unicode_ci est plus lente 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 benchmark, l'utilisation de utf8_unicode_ci est plus lente que utf8_general_ci de 7,9%.
2 votes
Voir aussi stackoverflow.com/questions/1036454/
8 votes
Si vous aimez
utf8[mb4]_unicode_ci
vous mai commeutf8[mb4]_unicode_520_ci
encore plus.9 votes
Je ne sais pas ce que j'en pense - au lieu de corriger leur implémentation pour suivre le dernier standard Unicode, ils gardent la version obsolète comme valeur par défaut et les gens doivent ajouter "520" pour utiliser la bonne version maintenant. Et ce n'est pas compatible en avant et en arrière parce que vous ne pouvez pas utiliser la version "520" sur les anciennes versions de MySQL. Pourquoi n'ont-ils pas simplement mis à jour la collation existante ? Même chose avec "mb4", vraiment. Quel code dépendait vraiment de l'ancien comportement, limité/obsolète, pour justifier de le garder comme valeur par défaut ?
9 votes
Le choix par défaut de la version 8.0, qui est de
utf8mb4_0900_ai_ci
.0 votes
Et 8.0 a accéléré les comparaisons utf8 de manière significative. (Probablement toutes les collations de utf8/utf8mb4)