OVH Cloud OVH Cloud

[mySQL] problème d'accents dans query

23 réponses
Avatar
Denis Beauregard
Bonjour,

Sur un site que j'ai développé il y a quelques années, je pouvais
faire une recherche telle que si je recherche une lettre accentuée,
mysql trouve la lettre accentuée ou non. Ainsi, la recherche suivante

http://www.sgcf.com/zacharie/reponse.php?Auteurs=b%E9auregard&Titre=&Cote=&Sujet=

où je demande béauregard, va trouver beauregard.

Je suis en train de développer un nouveau site à partir de zéro et
j'ai donc créé une nouvelle base de données et écrit du code
entièrement nouveau. Mais la procédure pour préparer le query est
à peu près la même.

ancienne version : $mot = $_GET puis str_replace pour remplacer * par
%
et l'espace par % puis addslashes et $query = "select etc.

nouvelle version : $mot = valeur("mot") où valeur est cette fonction:

function Valeur ($cible, $def) {
$rep = $def;
if (isset($_POST[$cible])) { $rep =$_POST[$cible]; };
if (isset($_GET[$cible])) { $rep =$_GET[$cible]; };
$rep = str_replace("*","%",$rep);
$rep = str_replace("\"","",$rep);
$rep = str_replace(";","",$rep);
$rep = str_replace("?","_",$rep);
return (addslashes($rep));
};

donc, je prends l'argument dans $_GET ou $_POST, je remplace les
* et ? par des équivalents SQL, et j'enlève les \ et ; pour me
protéger contre des infections de code. Les modifications sont
équivalentes.

Dans les deux cas, le SELECT utilise LIKE pour la comparaison.
Mais dans mon nouveau code, hébert ne trouve pas hebert !

Le champ dans la base SQL est pourtant codé comme
latin1_general_ci dans les deux cas, l'un est text et l'autre
un varchar(36). Dans les deux cas, pas d'énoncé dans l'entête
pour choisir un jeu de caractères.

Quel est le problème de mon nouveau code ?


Denis

10 réponses

1 2 3
Avatar
Mickaël Wolff
Pascal G. a écrit :

microtime() te la donne en ms.


Non, en µs ;)

Je viens d'effectuer l'exemple donné dans l'article en mettant
usleep(2000000); et j'ai eu en résultat : "Did nothing in 1.999960899353
seconds", ce qui semble quand même assez précis. (ps : je suis avec un
portable, OS vista que j'utile pour un peu de dév et démo, et une
installation WAMP !).


En fait, ça n'a rien à voir avec l'OS. C'est un problème de
représentation des nombres réels, et le fait que usleep de PHP utilises
les flotants. Du coup, on hérite des problèmes de précision des flotants.

Ma réflexion sur l'idée du gain ou pas de REGEXP faisait suite au propos
de Mickäel W. Sans entrer dans l'étude d'un bench en php (qui peut être
serait hors charte), je serai assez surpris qu'il n'y ait pas ici un
habitué qui sache déjà ce qu'il est préférable d'utiliser (LIKE ou REGEXP).


Ni l'un ni l'autre.

Et en faisant une petite recherche Internet, la synthèse des 4 ou 5
pages que j'ai parcourues semblent indiquer que LIKE est plus rapide,
mais que REGEXP permet des recherches plus pointues. (dont un site qui
obtient un résultat optimum en combinant LIKE et REGEXP).


C'est logique que like est plus rapide que regexp. La clause like
fait appel à une machine à état moins complèxe - du fait d'un ensemble
plus restreint d'états - que celle nécessaire à la clause propriétaire
regexp.

Il ne faut pas perdre de vu que SQL est un langage de requêtage conçu
pour un usage quotidien. À une époque où apprendre un langage pour
consulter une base de données n'était pas aberrant. Ce qui fait que
l'usage de like était tout à fait indiqué. Cependant, vu l'usage qui est
fait des requêtes SQL, il ne faut pas oublier que la requête de
consultation des données est souvent générée automatiquement, et doit
donc prendre en compte les problèmes de performances de la requête. On
ne peut pas se permettre de générer une requête qui ignorera les index
(comme le fait la plupart du temps une requête utilisant like).

Mais mon expérience ne se limite qu'à l'usage de deux SGBDR SQL. Je
serais intéressé de confronter mes constatations à celles d'un
utilisateur ou développeur d'une base telle Oracle ou Postgre.

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Avatar
Denis Beauregard
Le Thu, 10 Sep 2009 04:09:49 +0200, Mickaël Wolff
écrivait dans fr.comp.applications.sgbd:

Il ne faut pas perdre de vu que SQL est un langage de requêtage conçu
pour un usage quotidien. À une époque où apprendre un langage pour
consulter une base de données n'était pas aberrant. Ce qui fait que
l'usage de like était tout à fait indiqué. Cependant, vu l'usage qui est
fait des requêtes SQL, il ne faut pas oublier que la requête de
consultation des données est souvent générée automatiquement, et doit
donc prendre en compte les problèmes de performances de la requête. On
ne peut pas se permettre de générer une requête qui ignorera les index
(comme le fait la plupart du temps une requête utilisant like).

Mais mon expérience ne se limite qu'à l'usage de deux SGBDR SQL. Je
serais intéressé de confronter mes constatations à celles d'un
utilisateur ou développeur d'une base telle Oracle ou Postgre.



L'application en soi ainsi que les usagers ont leur importance dans le
choix de la façon d'interroger la BDD. Par exemple, si les mots
utilisés pour les recherches sont toujours complets (parce qu'ils
proviennent d'autres données ou que l'on recherche toujours des mots
entiers comme avec Google), alors == ou === est la solution la plus
rapide. Par contre, si la donnée vient d'un humain, que le mot peut
s'écrire de différentes façons et que l'on ne veut pas obliger le
client à essayer tous les mots possibles, alors il faut passer par
LIKE ou REGEXP. Et si l'usager habituel n'a probablement aucune
idée de ce qu'est une expression régulière, alors LIKE me semble le
choix logique.

On m'a demandé d'adapter à Internet un outil existant déjà sous
Windows et cette outil ajoute un % à la fin des noms. En fait,
une requête typique serait par exemple WOL et MIC*EL que je
transforme en WOL% et %MIC%EL% avant de faire la recherche. Je
ne sais pas pourquoi tu ne veux pas que j'utilise LIKE, mais c'est
soit LIKE, soit REGEXP si on a des jetons, et LIKE est plus rapide.
De plus, la syntaxe n'est pas la même. Un REGEXP où je reprends
tel quel l'argument utilisé par LIKE ne trouve rien.

Quant à mon application, pour le pire cas, j'ai quelque chose comme :

version 1 - autour de 25 secondes. Pas de champ INDEX. Une seule
table.

version 2 - autour de 1,5 secondes. Champ INDEX pour le 1er argument.
Ce champ est un varchar. De plus, le tableau est déjà trié sur ce
champ. Il contient plus de 2 millions d'enregistrements, autour de
120 000 mots différents pour le champ indexé. 2 tables, une triée
par le champ INDEX et utilisée pour les recherches, et une pas
vraiment triée mais contenant plusieurs champs qui ne sont pas
utilisés pour la recherche.


Denis
Avatar
Pascal G.
microtime() te la donne en ms



Non, en µs ;)



oui effectivement. je commençais à ... faiblir en fin de journée ;)


@+
pascal
Avatar
Denis Beauregard
Le Thu, 10 Sep 2009 07:37:06 +0200, "Pascal G."
écrivait dans fr.comp.applications.sgbd:


microtime() te la donne en ms





Non, en µs ;)





En fait, cela retourne par défaut 2 valeurs, soit la fraction
de seconde et la seconde. Donc, ce n'est ni les ms, ni les µs,
mais des secondes.

oui effectivement. je commençais à ... faiblir en fin de journée ;)



Fin de journée ? Ah, la terre commence à tourner dans le mauvais
sens.


Denis
Avatar
Pascal G.
Bonjour



microtime() te la donne en ms





Non, en µs ;)





En fait, cela retourne par défaut 2 valeurs, soit la fraction
de seconde et la seconde. Donc, ce n'est ni les ms, ni les µs,
mais des secondes.



tu chipotes ;-)


oui effectivement. je commençais à ... faiblir en fin de journée ;)



Fin de journée ? Ah, la terre commence à tourner dans le mauvais
sens.



Au moment de mon post, il était 23H35, et now(), il est 7H56. Le tout en
Local, bien sur.
Depuis j'ai dormi, il me semble que tout est logique (mr spock).

@+
pascal
Avatar
Denis Beauregard
Le Thu, 10 Sep 2009 07:59:30 +0200, "Pascal G."
écrivait dans fr.comp.applications.sgbd:

oui effectivement. je commençais à ... faiblir en fin de journée ;)



Fin de journée ? Ah, la terre commence à tourner dans le mauvais
sens.



Au moment de mon post, il était 23H35, et now(), il est 7H56. Le tout en
Local, bien sur.
Depuis j'ai dormi, il me semble que tout est logique (mr spock).



Le premier est pourtant posté à 01:37 (du matin) à mon heure locale,
ma réponse à 01:43 et le message auquel je réponds à 01:57.

J'ai l'impression que le 1er message est parti quand tu as démarré
ton PC et non hier soir.


Denis
Avatar
Pascal G.
oui effectivement. je commençais à ... faiblir en fin de journée ;)



Fin de journée ? Ah, la terre commence à tourner dans le mauvais
sens.



Au moment de mon post, il était 23H35, et now(), il est 7H56. Le tout en
Local, bien sur.
Depuis j'ai dormi, il me semble que tout est logique (mr spock).



Le premier est pourtant posté à 01:37 (du matin) à mon heure locale,
ma réponse à 01:43 et le message auquel je réponds à 01:57.

J'ai l'impression que le 1er message est parti quand tu as démarré
ton PC et non hier soir.



Non, mais bon, peu importe finalement.
http://www.cijoint.fr/cj200909/cijGByrkZJ.jpg


@+
pascal
Avatar
Olivier Miakinen
Le 10/09/2009 15:31, Denis Beauregard a écrit :

Au moment de mon post, il était 23H35, et now(), il est 7H56. Le tout en
Local, bien sur.
Depuis j'ai dormi, il me semble que tout est logique (mr spock).



Le premier est pourtant posté à 01:37 (du matin) à mon heure locale,
ma réponse à 01:43 et le message auquel je réponds à 01:57.



Vous ne parlez pas du même article.


Pascal parlait de :
Message-ID: <4aa81fb8$0$10249$
Heure française : 09/09/2009 23:35 +0200
Ton heure locale : 10/09/2009 05:35 -0400


Tu parles de :
Date: Thu, 10 Sep 2009 07:37:06 +0200
Message-ID: <4aa8908b$0$406$
Heure française : 10/10/2009 07:37 +0200
Ton heure locale : 10/10/2009 01:37 -0400

de :
Message-ID:
Heure française : 10/10/2009 07:43 +0200
Ton heure locale : 10/10/2009 01:43 -0400

et de :
Message-ID: <4aa895cb$0$7791$
Heure française : 10/10/2009 07:59 +0200
Ton heure locale : 10/10/2009 01:59 -0400
Avatar
Pascal
Le Thu, 10 Sep 2009 04:09:49 +0200,
Mickaël Wolff a écrit :

Pascal G. a écrit :


> Ma réflexion sur l'idée du gain ou pas de REGEXP faisait suite au
> propos de Mickäel W. Sans entrer dans l'étude d'un bench en php
> (qui peut être serait hors charte), je serai assez surpris qu'il
> n'y ait pas ici un habitué qui sache déjà ce qu'il est préfér able
> d'utiliser (LIKE ou REGEXP).
Ni l'un ni l'autre.

> Et en faisant une petite recherche Internet, la synthèse des 4 ou 5
> pages que j'ai parcourues semblent indiquer que LIKE est plus
> rapide, mais que REGEXP permet des recherches plus pointues. (dont
> un site qui obtient un résultat optimum en combinant LIKE et
> REGEXP).
C'est logique que like est plus rapide que regexp. La clause like
fait appel à une machine à état moins complèxe - du fait d'un
ensemble plus restreint d'états - que celle nécessaire à la clause
propriétaire regexp.



Je prend le train en marche.

L'avantage de LIKE c'est la possibilité d'utiliser les index dans
certains cas.
Si le début de la chaine est fixe ('ABC%') l'index sera utilisé
contrairement à '%ABC%'.

Au vue de la taille de la base de Denis, je me demande si une table
temporaire type dictionnaire sur les patronymes ne serait pas le mieux ?

J'avais envisagé le cas pour moi. C'est plus proche de la
normalisation au niveau SQL. Ça permet également
d'autoriser plusieurs noms pour une personne (évolution de la graphie
par exemple). Par contre ça me posait des problèmes ailleurs que j'ai
oublié. Et comme j'ai pas 2M d'enregistrements :)

Pascal
Avatar
Alarch
Denis Beauregard wrote:

C'est dommage que cette distinction très importante ne soit pas plus
mise en lumière. J'ai lu le manuel de mysql et les sites bidons qui
sont favorisés par l'algorythme farfelu de Google (préférence donnée
au nombre de pages sur un site et aux blogues et non aux sites qui
devraient être la référence). Je n'ai pas vu d'emphase sur la
différence, peut-être parce que tout le monde utilise la valeur par
défaut...


Denis



Eh eh ! Et attends le jour où pour une quelconque raison on va te faire
passer sous utf-8 ! Là il y a de la rigolade, entre la base, ses
sauvegardes, les interfaces, ça en affiche des trucs bizarres avant de
dompter la bête !
1 2 3