OVH Cloud OVH Cloud

[liaison MySQL] pb distinct dans requete

6 réponses
Avatar
Manuel Pavy
Bonjour,

j'ai un double probleme : tout d'abord (le moins grave) ma requete est
extremment gourmande : 6s de temps de réponse (depuis un serveur MySQL).
Mais ca, ce n est que depuis mon client MySQL.

Le plus embetant, est que lorsque que je teste cette meme requete avec
WD (clic droit "tester la requete"), eh bien, ... je ne connais pas le
temps, puisqu'apparement le distinct n est pas pris en compte et je ne l
ai pas laisser tourné jusqu au bout (apres 440 000 lignes, je me suis
dit qu il fallait pas faire surchauffer le serveur).

Donc voila la requete :
SELECT DISTINCT UniteRecherche.NomUR AS NomUR
from UniteRecherche, CentreOnera_Departement, Departement, CentreOnera,
Droit, Utilisateur, UniteDeTravail
where Droit.IDUtilisateur=1
and ((Droit.IDDepartement=Departement.IDDepartement
and Departement.IDDepartement=CentreOnera_Departement.IDDepartement
and
UniteRecherche.IDCentre_Departement=CentreOnera_Departement.IDCentre_Departement)

or (Droit.IDCentre=CentreOnera.IDCentre
and CentreOnera.IDCentre=CentreOnera_Departement.IDCentre
and
UniteRecherche.IDCentre_Departement=CentreOnera_Departement.IDCentre_Departement))

Merci pour votre aide,

Manu

6 réponses

Avatar
Manuel Pavy
Finalement, j ai tenté de tester la fenetre comme ca, et ca marche : seul les éléments
trouvés avec le client MySQL sont pris en compte. Il n en reste pas moins que la
requete est lourde, mais c est pas tres grave (ca vient du OR je suppose).

Manu




Manuel Pavy a écrit :

Bonjour,

j'ai un double probleme : tout d'abord (le moins grave) ma requete est
extremment gourmande : 6s de temps de réponse (depuis un serveur MySQL).
Mais ca, ce n est que depuis mon client MySQL.

Le plus embetant, est que lorsque que je teste cette meme requete avec
WD (clic droit "tester la requete"), eh bien, ... je ne connais pas le
temps, puisqu'apparement le distinct n est pas pris en compte et je ne l
ai pas laisser tourné jusqu au bout (apres 440 000 lignes, je me suis
dit qu il fallait pas faire surchauffer le serveur).

Donc voila la requete :
SELECT DISTINCT UniteRecherche.NomUR AS NomUR
from UniteRecherche, CentreOnera_Departement, Departement, CentreOnera,
Droit, Utilisateur, UniteDeTravail
where Droit.IDUtilisateur=1
and ((Droit.IDDepartementÞpartement.IDDepartement
and Departement.IDDepartementÎntreOnera_Departement.IDDepartement
and
UniteRecherche.IDCentre_DepartementÎntreOnera_Departement.IDCentre_Departement)

or (Droit.IDCentreÎntreOnera.IDCentre
and CentreOnera.IDCentreÎntreOnera_Departement.IDCentre
and
UniteRecherche.IDCentre_DepartementÎntreOnera_Departement.IDCentre_Departement))

Merci pour votre aide,

Manu


Avatar
elecoest
> j'ai un double probleme : tout d'abord (le moins grave) ma requete est
extremment gourmande : 6s de temps de réponse (depuis un serveur MySQL).
Mais ca, ce n est que depuis mon client MySQL.



Tout dépend de la volumétrie engagée et de la cohérence des indexes.

Le plus embetant, est que lorsque que je teste cette meme requete avec
WD (clic droit "tester la requete"), eh bien, ... je ne connais pas le
temps, puisqu'apparement le distinct n est pas pris en compte et je ne l
ai pas laisser tourné jusqu au bout (apres 440 000 lignes, je me suis
dit qu il fallait pas faire surchauffer le serveur).



<avant de lire voir les conclusions sur la requete>
les 440 000 lignes s'expliquent facilement vu que chaque résultat valable
est multiplé par la cardinalité de Utilisateur encore multiplié par la
cardinalité de UniteDeTravail !

avec un exemple : 10 UniteDeTravail et 100 utilisateurs : nombre de lignes
mises en jeu x 10 x 100 (soit 1000 fois plus de lignes)

Donc voila la requete :



Attention les yeux !

SELECT DISTINCT UniteRecherche.NomUR AS NomUR
from UniteRecherche, CentreOnera_Departement, Departement,


CentreOnera,Droit, Utilisateur, UniteDeTravail
where Droit.IDUtilisateur=1
and ( ( Droit.IDDepartementÞpartement.IDDepartement
and


Departement.IDDepartementÎntreOnera_Departement.IDDepartement
and


UniteRecherche.IDCentre_DepartementÎntreOnera_Departement.IDCentre_Departe
ment
)
or (Droit.IDCentreÎntreOnera.IDCentre
and CentreOnera.IDCentreÎntreOnera_Departement.IDCentre
and


UniteRecherche.IDCentre_DepartementÎntreOnera_Departement.IDCentre_Departe
ment
)
)



Alors je dis bravo le produit cartésien ! où sont utilisées les table
Utilisateur et UniteDeTravail ?
Ensuite je ne sais même pas comment le SGBD comprend la requete :
CentreOnera_Departement est en jointure sur quelle table ? Departement ou
CentreOnera ?

Je vais paraitre peut-être méchant mais au vu de cette requête je comprends
que certains utilisateur WD pensent que les requetes c'est compliqué et que
c'est moins rapide que les ordres hxxx. En plus je n'ose même pas imaginé
d'où vient le distinct ? cela ne viendrait pas du fait que votre requete
renvoie plusieurs fois la même lignes (explication des x1000)?

Sinon connaissez vous la commande "EXPLAIN" en mysql. Elle devrait devenir
vite votre amie

Pour moi, voici comment je ferai le bébé :

1 requete qui renvoie les UniteRecherche.NomUR trouvé à partir des
départements avec laquelle j'alimente la table 1 (table Windev)

SELECT DISTINCT UniteRecherche.NomUR AS NomUR
from UniteRecherche UR, CentreOnera_Departement COD, Departement DPT, Droit
D
where D.IDUtilisateur=1
and D.IDDepartement=DPT.IDDepartement
and DPT.IDDepartement=COD.IDDepartement
and UR.IDCentre_Departement=COD.IDCentre_Departement

1 requete qui renvoie les UniteRecherche.NomUR trouvé à partir des centres
avec laquelle j'alimente la table 1 (table Windev)

SELECT DISTINCT UniteRecherche.NomUR AS NomUR
from UniteRecherche UR, CentreOnera_Departement COD, CentreOnera CO, Droit D
where D.IDUtilisateur=1
and D.IDCentreÎntreOnera.IDCentre
and CO.IDCentre=COD.IDCentre
and UR.IDCentre_Departement=COD.IDCentre_Departement

je fais un distinct en W-Langage entre ces 2 tables.

--
Emmanuel Lecoester
Formateur en SQL à ses heures perdues...




---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.618 / Virus Database: 397 - Release Date: 09/03/2004
Avatar
KPITN
Manuel Pavy wrote in
news::



tu fais un select sur 7 tables et tu n'a que 3 jointures

les tables : CentreOnera_Departement , Utilisateur et UniteDeTravail
n'ont rien a faire la , si elles ont leur place fait les jointures
manquante.


tu m'etonnes que le nombre d'enregistrement retourné est élévé
Avatar
Firetox
Bonjour,

effectivement la requete est sur 7 tables et les jointures ne sont pas
evidentes
a determiner. c'est pour ca que je conseil a mes programmeurs la mthodologie
suivante

: utiliser les LEFT JOIN ou JOIN (suivant si c'est une jointure ouverte ou
fermée) avec l'utilisation du USING (cle de jointure)

pourqoui ?

parceque avec cette syntaxe il n'est pas possible de fair eune jointure de
travers
le moteur MySQL verifie dans cette syntaxe si les cle existe dans les
tables, donc verifie au moins la coherence de la requete ex

SELECT *
FROM matable1 JOIN matable2 using (macleA,macleAA)
WHERE ......

si les tables ne sont pas jointes dans l'analyse correctement le moteur
MySQL vous le dira
ex : la colonne macleAA n'existe pas dans la table matable2 : dans ce cas la
jointure est fausse

de meme ca evite les jointure entre table sur des cle d'une autre (ce qui
ralenti enormement les requetes)
pour exemple : j'ai une requete sur 7 table dont 1 avec 80 million de lignes
qui remonte en 2 secondes ....

voila

le SQL c'est bien , mais ATTENTION les résultats sont dependant de la
cohérence des requetes
je pars du principe qu'une requetes ne doit mettre plus de 1 à 2 seconde
pour remonter le resultats
ensuite si le temps est plus important :

- verifier le nombre de lignes renvoyées et discuter de leur cohérence
(quel interets de renvoyer 3 miilions de lignes dans une table pour
l'utilisateur ? utiliser les LIMIT ?)
- verifier la requete par EXPLAIN
- verifier l'existance des index permettant cette requete de façon
optimal

voila

Bon dev
@+
Firetox


"Manuel Pavy" a écrit dans le message de news:

Bonjour,

j'ai un double probleme : tout d'abord (le moins grave) ma requete est
extremment gourmande : 6s de temps de réponse (depuis un serveur MySQL).
Mais ca, ce n est que depuis mon client MySQL.

Le plus embetant, est que lorsque que je teste cette meme requete avec
WD (clic droit "tester la requete"), eh bien, ... je ne connais pas le
temps, puisqu'apparement le distinct n est pas pris en compte et je ne l
ai pas laisser tourné jusqu au bout (apres 440 000 lignes, je me suis
dit qu il fallait pas faire surchauffer le serveur).

Donc voila la requete :
SELECT DISTINCT UniteRecherche.NomUR AS NomUR
from UniteRecherche, CentreOnera_Departement, Departement, CentreOnera,
Droit, Utilisateur, UniteDeTravail
where Droit.IDUtilisateur=1
and ((Droit.IDDepartementÞpartement.IDDepartement
and Departement.IDDepartementÎntreOnera_Departement.IDDepartement
and



UniteRecherche.IDCentre_DepartementÎntreOnera_Departement.IDCentre_Departe
ment)

or (Droit.IDCentreÎntreOnera.IDCentre
and CentreOnera.IDCentreÎntreOnera_Departement.IDCentre
and



UniteRecherche.IDCentre_DepartementÎntreOnera_Departement.IDCentre_Departe
ment))

Merci pour votre aide,

Manu



Avatar
Roumegou
Excellents conseils de Firetox.
Un autre conseil : celui du mec un peu feignant et qui n'aime pas quand
ça commence à chauffer un peu trop sous son crane ...
Faire un mdb access; lier ses tables mysql. Faire sa requête avec le
requeteur graphique d'access en double cliquant sur les liens pour
définir le sens; tester puis pomper et adapter le code sql produit.
Ensuite essayer d'optimiser avec le EXPLAIN.

Firetox a présenté l'énoncé suivant :
Bonjour,

effectivement la requete est sur 7 tables et les jointures ne sont pas
evidentes
a determiner. c'est pour ca que je conseil a mes programmeurs la mthodologie
suivante

utiliser les LEFT JOIN ou JOIN (suivant si c'est une jointure ouverte ou


fermée) avec l'utilisation du USING (cle de jointure)

pourqoui ?

parceque avec cette syntaxe il n'est pas possible de fair eune jointure de
travers
le moteur MySQL verifie dans cette syntaxe si les cle existe dans les
tables, donc verifie au moins la coherence de la requete ex

SELECT *
FROM matable1 JOIN matable2 using (macleA,macleAA)
WHERE ......

si les tables ne sont pas jointes dans l'analyse correctement le moteur
MySQL vous le dira
ex : la colonne macleAA n'existe pas dans la table matable2 : dans ce cas la
jointure est fausse

de meme ca evite les jointure entre table sur des cle d'une autre (ce qui
ralenti enormement les requetes)
pour exemple : j'ai une requete sur 7 table dont 1 avec 80 million de lignes
qui remonte en 2 secondes ....

voila

le SQL c'est bien , mais ATTENTION les résultats sont dependant de la
cohérence des requetes
je pars du principe qu'une requetes ne doit mettre plus de 1 à 2 seconde
pour remonter le resultats
ensuite si le temps est plus important :

- verifier le nombre de lignes renvoyées et discuter de leur cohérence
(quel interets de renvoyer 3 miilions de lignes dans une table pour
l'utilisateur ? utiliser les LIMIT ?)



Oui mais attention car le LIMIT n'existe pas toujours sur tous les
SGBD. En oracle, ce genre de chose est hyper dur à faire.

- verifier la requete par EXPLAIN
- verifier l'existance des index permettant cette requete de façon
optimal

voila




--
Eric Roumegou
http://cerbermail.com/?TSoulBerPA
(cliquez sur le lien ci-dessus pour me contacter en privé)
Avatar
Manuel Pavy
Merci à tous,
vos différents conseils m'ont bien aidé. Le mieux est effectivement la solution
d'eleocest, mais je préfere garder ma requete en SQL (on sait jamais si par la
suite la base peut servir pour autre langage que WD), je me suis donc apercu de
l'erreur principale : l'utilisation des tables Utilisateur et UniteDeTravail dans
le from alors qu'elle n'ont rien à y faire.
Je garde le OR et la requete devient acceptable (0.55 s) pour 187 lignes.

Cependant, le fait de tester la requete grace au testeur de WD, il y a tjs un pb
alors que lorsque je l execute dans mon projet, ca marche nickel (je retrouve bien
mes 187 lignes).

Merci beaucoup en tous cas,

Manu

Roumegou a écrit :

Excellents conseils de Firetox.
Un autre conseil : celui du mec un peu feignant et qui n'aime pas quand
ça commence à chauffer un peu trop sous son crane ...
Faire un mdb access; lier ses tables mysql. Faire sa requête avec le
requeteur graphique d'access en double cliquant sur les liens pour
définir le sens; tester puis pomper et adapter le code sql produit.
Ensuite essayer d'optimiser avec le EXPLAIN.

Firetox a présenté l'énoncé suivant :
> Bonjour,
>
> effectivement la requete est sur 7 tables et les jointures ne sont pas
> evidentes
> a determiner. c'est pour ca que je conseil a mes programmeurs la mthodologie
> suivante
>
>> utiliser les LEFT JOIN ou JOIN (suivant si c'est une jointure ouverte ou
> fermée) avec l'utilisation du USING (cle de jointure)
>
> pourqoui ?
>
> parceque avec cette syntaxe il n'est pas possible de fair eune jointure de
> travers
> le moteur MySQL verifie dans cette syntaxe si les cle existe dans les
> tables, donc verifie au moins la coherence de la requete ex
>
> SELECT *
> FROM matable1 JOIN matable2 using (macleA,macleAA)
> WHERE ......
>
> si les tables ne sont pas jointes dans l'analyse correctement le moteur
> MySQL vous le dira
> ex : la colonne macleAA n'existe pas dans la table matable2 : dans ce cas la
> jointure est fausse
>
> de meme ca evite les jointure entre table sur des cle d'une autre (ce qui
> ralenti enormement les requetes)
> pour exemple : j'ai une requete sur 7 table dont 1 avec 80 million de lignes
> qui remonte en 2 secondes ....
>
> voila
>
> le SQL c'est bien , mais ATTENTION les résultats sont dependant de la
> cohérence des requetes
> je pars du principe qu'une requetes ne doit mettre plus de 1 à 2 seconde
> pour remonter le resultats
> ensuite si le temps est plus important :
>
> - verifier le nombre de lignes renvoyées et discuter de leur cohérence
> (quel interets de renvoyer 3 miilions de lignes dans une table pour
> l'utilisateur ? utiliser les LIMIT ?)

Oui mais attention car le LIMIT n'existe pas toujours sur tous les
SGBD. En oracle, ce genre de chose est hyper dur à faire.

> - verifier la requete par EXPLAIN
> - verifier l'existance des index permettant cette requete de façon
> optimal
>
> voila
>

--
Eric Roumegou
http://cerbermail.com/?TSoulBerPA
(cliquez sur le lien ci-dessus pour me contacter en privé)