798 votes

Quel est le meilleur classement à utiliser pour MySQL (PHP)

Je me demandais si il y a un "meilleur" choix pour le classement dans MySQL pour un site généraliste où vous n'êtes pas 100% de ce qui sera entré? Je comprends que tous les codages doivent être les mêmes, telles que MySQL, Apache, HTML et rien à l'intérieur de PHP.

Dans le passé, j'ai mis en PHP pour la sortie en "UTF-8", mais le classement ne ce match dans MySQL? Je pense que c'est un de l'UTF-8, mais j'ai utilisé utf8_unicode_ci, utf8_general_ci, et utf8_bin avant.

671voto

Eran Galperin Points 49594

La principale différence est la précision du tri (lorsque l'on compare les caractères de la langue) et de la performance. La seule particularité est utf8_bin qui est de la comparaison des caractères dans un format binaire.

utf8_general_ci est un peu plus rapide que d' utf8_unicode_ci, mais moins précis (pour tri). La langue spécifique à l'encodage utf8 (comme utf8_swedish_ci) contiennent des règles de la langue que de les rendre le plus précis pour trier ces langues. La plupart du temps j'utilise utf8_unicode_ci (je préfère la précision de petites améliorations de performance), à moins que j'ai une bonne raison de préférer une langue spécifique.

Vous pouvez en lire plus sur certains jeux de caractères unicode sur le manuel MySQL - http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

153voto

Vegard Larsen Points 4850

En fait, vous voudrez probablement utiliser utf8_unicode_ci ou utf8_general_ci.

  • utf8_general_ci sortes en enlevant tous les accents et le tri comme si c'était ASCII
  • utf8_unicode_ci utilise l'Unicode ordre de tri, de sorte qu'il trie correctement dans d'autres langues

Toutefois, si vous utilisez uniquement ce pour stocker du texte anglais, ceux-ci ne devraient pas différer.

125voto

Guus Points 1132

Être très, très conscient de ce problème qui peut se produire lors de l'utilisation de utf8_general_ci.

MySQL ne fera pas de distinction entre certains caractères dans les instructions select, si le collate utf8_general_ci est utilisé. Cela peut conduire à de très méchants bugs - en particulier par exemple, où les noms d'utilisateurs sont concernés. En fonction de l'application qui utilise les tables de base de données, ce problème pourrait permettre à des utilisateurs malveillants afin de créer un nom d'utilisateur correspondant à un compte d'administrateur.

Ce problème s'expose à tout le moins dans les 5 premiers.versions x - je ne sais pas si ce comportement a changé plus tard.

Je ne suis pas DBA, mais pour éviter ce problème, je vais toujours avec 'utf8-bin" à la place de la casse.

Le script ci-dessous décrit le problème par exemple.

-- first, create a sandbox to play in
CREATE DATABASE `sandbox`;
use `sandbox`;

-- next, make sure that your client connection is of the same 
-- character/collate type as the one we're going to test next:
charset utf8 collate utf8_general_ci

-- now, create the table and fill it with values
CREATE TABLE `test` (`key` VARCHAR(16), `value` VARCHAR(16) )
    CHARACTER SET utf8 COLLATE utf8_general_ci;

INSERT INTO `test` VALUES ('Key ONE', 'value'), ('Key TWO', 'valúe');

-- (verify)
SELECT * FROM `test`;

-- now, expose the problem/bug:
SELECT * FROM test WHERE `value` = 'value';

--
-- Note that we get BOTH keys here! MySQLs UTF8 collates that are 
-- case insensitive (ending with _ci) do not distinguish between 
-- both values!
--
-- collate 'utf8_bin' doesn't have this problem, as I'll show next:
--

-- first, reset the client connection charset/collate type
charset utf8 collate utf8_bin

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Note that we get just one key now, as you'd expect.
--
-- This problem appears to be specific to utf8. Next, I'll try to 
-- do the same with the 'latin1' charset:
--

-- first, reset the client connection charset/collate type
charset latin1 collate latin1_general_ci

-- next, convert the values that we've previously inserted
-- in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_general_ci;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Again, only one key is returned (expected). This shows 
-- that the problem with utf8/utf8_generic_ci isn't present 
-- in latin1/latin1_general_ci
--
-- To complete the example, I'll check with the binary collate
-- of latin1 as well:

-- first, reset the client connection charset/collate type
charset latin1 collate latin1_bin

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_bin;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Again, only one key is returned (expected).
--
-- Finally, I'll re-introduce the problem in the exact same 
-- way (for any sceptics out there):

-- first, reset the client connection charset/collate type
charset utf8 collate utf8_generic_ci

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

-- now, re-check for the problem/bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Two keys.
--

DROP DATABASE sandbox;

49voto

Tomalak Points 150423

Les classements affecter la façon dont les données sont triées et dont les chaînes sont comparées les unes aux autres. Cela signifie que vous devez utiliser le classement à la plupart de vos utilisateurs attendent.

Exemple tiré de la documentation:

utf8_general_ci est également satisfaisante en allemand et en français, à l'exception de que ‘ß' est égal à ‘s', et de ne pas le "ss". Si cela est acceptable pour votre l'application, alors vous devriez utiliser utf8_general_ci parce que c'est plus rapide. Sinon, utilisez utf8_unicode_ciparce que il est plus précis.

Donc, ça dépend de votre base d'utilisateurs et sur combien vous avez besoin de corriger le tri. Pour un anglais de base de l'utilisateur, utf8_general_ci devrait suffire, pour les autres langues, comme le suédois, spécial classements ont été créés.

23voto

Phil Points 121

Essentiellement, cela dépend de la façon dont vous pensez à une chaîne.

J'ai toujours utiliser utf8_bin à cause du problème mis en évidence par Guus. À mon avis, d'autant que la base de données devraient être concernés, une chaîne de caractères n'est encore qu'une chaîne de caractères. Une chaîne est un nombre de caractères UTF-8. Un personnage a une représentation binaire alors, pourquoi est-il nécessaire de connaître la langue que vous utilisez? Habituellement, les gens seront de la construction de bases de données pour les systèmes avec le champ d'application pour les sites multilingues. C'est le point entier de l'utilisation de l'UTF-8 comme un jeu de caractères. Je suis un peu une pureist mais je pense que le bug risques fortement l'emportent sur le léger avantage que vous pouvez obtenir sur l'indexation. Toute langue règles connexes doit être fait à un niveau beaucoup plus élevé que le SGBD.

Dans mes livres "valeur" ne devrait jamais dans un million d'années égal à "valúe".

Si je veux stocker un champ de texte et faire une recherche insensible à la casse, je vais utiliser MYSQL fonctions de chaînes de caractères avec des fonctions PHP comme LOWER() et la fonction php strtolower().

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X