OVH Cloud OVH Cloud

Optimiastion de ma requete SQL

2 réponses
Avatar
ernond_paul
Bonjour, j'ai une requete assez complexe, beaucoup trop, et du coup
elle sature le serveur Mysql, pouvez vous m'aider à l'optimiser ?

(la réponse à cette question est surement "OUI"), donc guidez moi
SVP...

Voici la requete :


SELECT
distinctrow(contacts.id_membre),
typeadh.fr AS type_adherant_Nom,
ecoles.ecole AS ecole_Nom,
civilite.fr AS civilite_Nom,
secteur.fr AS secteur_Nom,
newsletter.email AS newsletter_emailMASTER,
etatcivil.email1 AS newsletter_emailALT1,
etatcivil.email2 AS newsletter_emailALT2,
filiere.filiere AS filiere_Nom,
promo.promo AS promotioNom,
pays.fr AS pays_Nom,
newsletters.*
FROM
contacts,
adherant,
ecole,
ecoles,
etatcivil,
civilite,
job,
secteur,
newsletter,
filiere,
promo,
pays,
typeadh,
newsletters
LEFT JOIN newsletters_pays
ON (newsletters.nid = newsletters_pays.nid)
LEFT JOIN newsletters_ecoles
ON (newsletters.nid = newsletters_ecoles.nid)
LEFT JOIN newsletters_filieres
ON (newsletters.nid = newsletters_filieres.nid)
LEFT JOIN newsletters_type_adherents
ON (newsletters.nid = newsletters_type_adherents.nid)
LEFT JOIN newsletters_promotions
ON (newsletters.nid = newsletters_promotions.nid)
LEFT JOIN newsletters_secteurs
ON (newsletters.nid = newsletters_secteurs.nid)

WHERE
(contacts.accord = 1) AND
(contacts.id_membre = adherant.id_membre) AND
(contacts.id_pays = pays.id_pays) AND

(adherant.adh_type = typeadh.id_typeadh) AND

(ecole.id_membre = adherant.id_membre) AND
(ecole.id_ecole = ecoles.id_ecole) AND
(ecole.id_filiere = filiere.id_filiere) AND
(ecole.id_promo = promo.id_promo) AND

(etatcivil.id_membre = adherant.id_membre) AND
(etatcivil.id_civilite = civilite.id_civilite) AND

(job.id_membre = adherant.id_membre) AND
(job.id_secteur = secteur.id_secteur) AND

(newsletter.id_membre = adherant.id_membre) AND

(newsletters.sended = 0);




si vous avez besoin de plus de details, je vous les donnerais...

Merci de votre attention.

2 réponses

Avatar
Michaël
Lo,

Le 12.05.2004 13:03, Paul a écrit :
Bonjour, j'ai une requete assez complexe, beaucoup trop, et du coup
elle sature le serveur Mysql, pouvez vous m'aider à l'optimiser ?



Première psite : as tu bien vérifié si les champs qui entrent en jeu dans les
jointures sont bien indexés ?

Cdt,
Michaël
Avatar
Fred BROUARD - SQLpro
1) DistinctRow est une imbécilité d'Access. Cela ne va certainement pas améliorer les perf !
A lire : http://sqlpro.developpez.com/SQL_AZ_E.html#Doublon

2) tu fais des jointures tantôt dans le ON tantôt dans le WHERE c'est particulièrement illogique, surtout en jointures
externe gauche (cela va à l'encontre) !

3) l'utilisation de l'étoile * est particulièrement contre performant

4) tu n'utilise aucun alias

5) et c'est le plus grave tu mélange deux styles de jointure dans le wehre et en outer join !!!

6) les parenthèses que tu as mise sont toutes inutiles

Conclusion il est temps d'apprendre le SQL !!!!!!!!!!!!!!!!!!!!!!!!!!!


SELECT c.id_membre,
ta.fr AS type_adherant_Nom,
es.ecole AS ecole_Nom,
cv.fr AS civilite_Nom,
s.fr AS secteur_Nom,
nl.email AS newsletter_emailMASTER,
ec.email1 AS newsletter_emailALT1,
ec.email2 AS newsletter_emailALT2,
f.filiere AS filiere_Nom,
p.promo AS promotioNom,
ps.fr AS pays_Nom

FROM contacts c
INNER JOIN adherant a
ON c.id_membre = a.id_membre
INNER JOIN typeadh ta
ON a.adh_type = ta.id_typeadh
INNER JOIN ecole e
ON a.id_membre = e.id_membre
AND a.id_membre = e.id_membre
INNER JOIN ecoles
ON e.id_ecole = es.id_ecole
INNER JOIN filiere f
ON e.id_filiere = f.id_filiere
INNER JOIN promo p
ON e.id_promo = p.id_promo
INNER JOIN etatcivil ec
ON ec.id_membre = a.id_membre
INNER JOIN civilite cv
ON ec.id_civilite = cv.id_civilite
INNER JOIN newsletter nl
ON a.id_membre = nl.id_membre
LEFT OUTER JOIN newsletters_pays nlp
ON nl.nid = nlp.nid
LEFT OUTER JOIN newsletters_ecoles nle
ON nm.nid = nle.nid
LEFT JOIN newsletters_filieres nlf
ON nl.nid = nlf.nid
LEFT JOIN newsletters_type_adherents nlta
ON nl.nid = nlta.nid
LEFT JOIN newsletters_promotions nlpm
ON nl.nid = nlpm.nid
LEFT JOIN newsletters_secteurs nls
ON nl.nid = nls.nid
INNER JOIN job j
ON a.id_membre = j.id_membre
INNER JOIN secteur s
ON j.id_secteur = s.id_secteur
INNER JOIN pays ps
ON c.id_pays = ps.id_pays

WHERE contacts.accord = 1
AND newsletters.sended = 0


La clause FROM contient l'arbre de jointure...

Comme l'a dit un autre internaute as tu des index sur toutes les colonnes de jointures ?

De toute façon Access est trop bourin pour que des requêtes comme cela (19 tables en jeu) soient perofrmantes...

A lire sur l'optimisation :
http://sqlpro.developpez.com/OptimSQL/SQL_optim.html

A +



--
Frédéric BROUARD, MVP MS SQL Server. Expert Langage SQL / Delphi / web
Livre SQL - col. Référence : http://sqlpro.developpez.com/bookSQL.html
Le site du SQL, pour débutants et pros : http://sqlpro.developpez.com
************************ www.datasapiens.com *************************

Paul a écrit:
Bonjour, j'ai une requete assez complexe, beaucoup trop, et du coup
elle sature le serveur Mysql, pouvez vous m'aider à l'optimiser ?

(la réponse à cette question est surement "OUI"), donc guidez moi
SVP...

Voici la requete :


SELECT
distinctrow(contacts.id_membre),
typeadh.fr AS type_adherant_Nom,
ecoles.ecole AS ecole_Nom,
civilite.fr AS civilite_Nom,
secteur.fr AS secteur_Nom,
newsletter.email AS newsletter_emailMASTER,
etatcivil.email1 AS newsletter_emailALT1,
etatcivil.email2 AS newsletter_emailALT2,
filiere.filiere AS filiere_Nom,
promo.promo AS promotioNom,
pays.fr AS pays_Nom,
newsletters.*
FROM
contacts,
adherant,
ecole,
ecoles,
etatcivil,
civilite,
job,
secteur,
newsletter,
filiere,
promo,
pays,
typeadh,
newsletters
LEFT JOIN newsletters_pays
ON (newsletters.nid = newsletters_pays.nid)
LEFT JOIN newsletters_ecoles
ON (newsletters.nid = newsletters_ecoles.nid)
LEFT JOIN newsletters_filieres
ON (newsletters.nid = newsletters_filieres.nid)
LEFT JOIN newsletters_type_adherents
ON (newsletters.nid = newsletters_type_adherents.nid)
LEFT JOIN newsletters_promotions
ON (newsletters.nid = newsletters_promotions.nid)
LEFT JOIN newsletters_secteurs
ON (newsletters.nid = newsletters_secteurs.nid)

WHERE
(contacts.accord = 1) AND
(contacts.id_membre = adherant.id_membre) AND
(contacts.id_pays = pays.id_pays) AND

(adherant.adh_type = typeadh.id_typeadh) AND

(ecole.id_membre = adherant.id_membre) AND
(ecole.id_ecole = ecoles.id_ecole) AND
(ecole.id_filiere = filiere.id_filiere) AND
(ecole.id_promo = promo.id_promo) AND

(etatcivil.id_membre = adherant.id_membre) AND
(etatcivil.id_civilite = civilite.id_civilite) AND

(job.id_membre = adherant.id_membre) AND
(job.id_secteur = secteur.id_secteur) AND

(newsletter.id_membre = adherant.id_membre) AND

(newsletters.sended = 0);




si vous avez besoin de plus de details, je vous les donnerais...

Merci de votre attention.