web-dev-qa-db-fra.com

utf8_bin contre utf_unicode_ci

Mon site Web de table

Website_Name//column name
Google
Facebook
Twitter
Orkut
Frype
Skype
Yahoo
Wikipedia

J'utilise le classement utf8_bin puis ma requête pour rechercher wikipedia dans le site Web est

Select Website_Name from Website where lower(Website_Name)='wikipedia'

Et si j'utilise utf8_unicode_ci, ma requête de sélection pour rechercher wikipedia sur le site Web est

Select Website_Name from Website where Website_Name='wikipedia'

Maintenant, je veux savoir quel classement est le meilleur en fonction des requêtes suivantes

32
user1432124

Cela dépend de ce dont vous avez besoin.

Le utf8_bin le classement compare les chaînes uniquement sur la base de leurs valeurs Unicode point de code . Si tous les points de code ont les mêmes valeurs, les chaînes sont égales. Cependant, cela tombe en morceaux lorsque vous avez des chaînes avec une composition différente pour combiner des marques (composées vs décomposées) ou des caractères qui sont canoniquement équivalents mais n'ont pas la même valeur de point de code. Dans certains cas, en utilisant utf8_bin entraînera la non-concordance des chaînes lorsque vous vous y attendez. Théoriquement, utf8_bin est le plus rapide car aucune normalisation Unicode n'est appliquée aux chaînes, mais ce n'est peut-être pas ce que vous voulez.

utf8_general_ci applique la normalisation Unicode en utilisant des règles spécifiques au langage et compare les chaînes sans tenir compte de la casse. utf8_general_cs fait de même, mais compare les chaînes en respectant la casse.

61
Delan Azabani

Personnellement, j'irais avec utf8_unicode_ci, si vous vous attendez à ce que la casse ne soit généralement pas importante pour les résultats que vous souhaitez trouver.

Les classements ne sont pas uniquement utilisés au moment de l'exécution, mais également lorsque MySQL crée des index. Donc, si l'une de ces colonnes apparaît dans un index, la recherche de données selon les règles de comparaison de ce classement sera à peu près aussi rapide que jamais.

Dans les cas où vous ne souhaitez pas de correspondance insensible à la casse, n'appliquez pas supérieur ou inférieur. Au lieu de cela, appliquez le mot clé BINARY devant la colonne utf8 pour forcer une comparaison littérale de points de code plutôt qu'une en fonction du classement.

mysql> create table utf8 (name varchar(24) charset utf8 collate utf8_general_ci, primary key (name));
Query OK, 0 rows affected (0.14 sec)

mysql> insert into utf8 values ('Roland');
Query OK, 1 row affected (0.00 sec)

mysql> insert into utf8 values ('roland');
ERROR 1062 (23000): Duplicate entry 'roland' for key 'PRIMARY'
mysql> select * from utf8 where name = 'roland';
+--------+
| name   |
+--------+
| Roland |
+--------+
1 row in set (0.00 sec)

mysql> select * from utf8 where binary name = 'roland';
Empty set (0.01 sec)

Cela devrait être beaucoup plus rapide que d'utiliser inférieur ou supérieur, car dans ces cas, MySQL doit d'abord faire une copie de la valeur de la colonne et modifier sa casse, puis appliquer la comparaison. Avec BINARY en place, il utilisera simplement l'index pour trouver des correspondances, puis effectuera une comparaison point par code jusqu'à ce qu'il trouve que les valeurs ne sont pas égales, ce qui sera généralement plus rapide.

13
Roland Bouman

J'utilisais 'utf8_unicode_ci' qui est par défaut par doctrine, j'ai dû le changer en:

 * @ORM\Table(name = "Table", options={"collate"="utf8_bin"})

Étant donné que certaines de mes clés primaires composites étaient constituées de champs de texte. Malheureusement, 'utf8_unicode_ci' a résolu "poistný" et "poistny" comme la même valeur de clé primaire et s'est terminé par un crash à doctrine insertion de vidage. Je ne pouvais pas simplement changer le classement d'une partie de la clé primaire composite, si de laisser tomber la table et de recréer. J'espère que cela fera gagner du temps à quelqu'un d'autre ..

8
Jiro Matchonson