Page 1 sur 1

Bug sous requete

Posté : 03 déc. 2007, 14:25
par costadelo
Bonjour @ tous,

J'utilise Mysql 5.026.

La table sur laquelle je travail est la suivante :

Code : Tout sélectionner

CREATE TABLE `regions_villes_fr` ( `id_ville` int(8) NOT NULL default '0', `ville` varchar(50) character set utf8 collate utf8_bin NOT NULL, `pronom` varchar(4) character set utf8 collate utf8_bin default NULL, `zipcode` varchar(5) character set utf8 collate utf8_bin NOT NULL, `region` varchar(50) character set utf8 collate utf8_bin NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
La requête suivante fonctionne bien,et me retourne des résultats :

Code : Tout sélectionner

SELECT * FROM utilisateur WHERE sexe LIKE 'F' AND gout=2 AND birth_date BETWEEN '1984-01-01' AND '1985-12-03' AND country = 'FR' AND city IN (SELECT `id_ville` FROM regions_villes_fr WHERE `region` = 'Ile-de-France' ) AND job =1 GROUP BY pseudo LIMIT 0,1800
Mais lorsque je retire le critère de sélection "job" et que je me retrouve avec la requête suivante, ca plante :

Code : Tout sélectionner

SELECT * FROM utilisateur WHERE sexe LIKE 'F' AND gout=2 AND birth_date BETWEEN '1984-01-01' AND '1985-12-03' AND country = 'FR' AND city IN (SELECT `id_ville` FROM regions_villes_fr WHERE `region` = 'Ile-de-France' ) GROUP BY pseudo LIMIT 0,1800
Que ce passe t'il ? Lorsque j'éxécute cette requête sous ma console sql, le serveur ne retourne rien, aucune réponse, il tourne il tourne, sans jamais s'arrêter...

Est ce que j'ai un pb au niveau de ma sous requete ? Lorsque ma sous requete est avant tous les autres critères de sélection, cela fonctionne bien, mais dès qu'elle se retrouve à la fin de la requete, ca plante...

Help me pliz

Merci d'avance pour vos réponses

Re: Bug sous requete

Posté : 03 déc. 2007, 15:28
par Hubert Roksor
le serveur ne retourne rien, aucune réponse, il tourne il tourne, sans jamais s'arrêter...
C'est probablement dû à ta sous-requête. À ma connaissance, MySQL n'optimise pas les sous-requêtes dans une comparaison IN, ce qui veut dire qu'il exécute une sous-requête par enregistrement. Il va te falloir convertir ta sous-requête en jointure.

Dans le doute, regarde toujours le résultat d'EXPLAIN avant d'exécuter une requête SELECT. D'ailleurs, si tu l'exécutes en mode console, fais un copier/coller du résultat ici pour qu'on vérifie.

Correction : c'est dû à ta sous-requête, mais aussi à ton manque d'indexes sur les tables. Il te faut un index sur "ydyle_regions_villes_fr.id_ville" mais aussi sur d'autres colonnes dans "utilisateur", celles qui servent à identifier des groupes d'utilisateur le plus rapidement. Poste le résultat de ton EXPLAIN pour plus d'info.

index

Code : Tout sélectionner

CREATE INDEX id_ville ON ydyle_regions_villes_fr (id_ville)
requête / jointure

Code : Tout sélectionner

SELECT u.* FROM utilisateur u JOIN ydyle_regions_villes_fr rv ON rv.id_ville = u.city WHERE u.sexe = 'F' AND u.gout = 2 AND u.birth_date BETWEEN '1984-01-01' AND '1985-12-03' AND u.country = 'FR' AND u.job = 1 AND rv.region = 'Ile-de-France' GROUP BY pseudo LIMIT 1800 OFFSET 0
Dernière chose, une fois un index sur id_ville ajouté et ta sous-requête transformée en jointure, ta requête fonctionnera à nouveau et à une vitesse raisonnable. Ne t'arrêtes surtout pas là, sans quoi tu auras le même problème dans trois mois, lorsque la quantité de données et le nombre de visiteur aura augmenté.

Posté : 03 déc. 2007, 15:38
par costadelo
mais alors pourquoi cela fonctionne lorsque ce critère de sélection qui comprend une sous requête n'est pas déclaré en dernier ?

Posté : 03 déc. 2007, 15:39
par Hubert Roksor
mais alors pourquoi cela fonctionne lorsque ce critère de sélection qui comprend une sous requête n'est pas déclaré en dernier ?
Aucune idée, poste ton EXPLAIN.

Posté : 03 déc. 2007, 15:55
par costadelo
ma sous requête fonctionne dans n'importe qu'elle situation désormais.
En effet, il manquait la déclaration de la clé primaire sur la table. Ce qui empêchait d'indexer le champ id_ville.

Merci pour vos réponses !

Posté : 03 déc. 2007, 15:59
par Hubert Roksor
De rien, à dans trois mois.

Ce serait sympa de poster l'EXPLAIN, ça m'éviterait la désagréable impression de ne pas être lu.