IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Requêtes MySQL Discussion :

optimisation de requête


Sujet :

Requêtes MySQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2011
    Messages : 25
    Par défaut optimisation de requête
    Bonjour,

    J'ai une requête qui me pose problème et que je n'arrive pas à optimiser.
    La voici :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    SELECT *
    FROM  envois, task , messages, sites 
     
    WHERE envois.idEnvoyeur = 1  AND envois.id = task.idEnvoi AND ( envois.status = 'ENV' OR (envois.status = 'PRG' AND envois.date_lance <= CURRENT_TIMESTAMP))
    AND envois.idMessage = messages.id AND messages.idSite = sites.id 
     
    ORDER BY envois.priority desc, envois.id asc, task.id asc
    LIMIT 0,150
    voila ce que donne l'explain

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    id 	select_type 	table 		type 	possible_keys 		key 		key_len 	ref 			rows 	Extra
     
    1 	SIMPLE 		task 		ALL 	idEnvoi 		NULL 		NULL 		NULL 			754315 	Using temporary; Using filesort
     
    1 	SIMPLE 		envois 		eq_ref 	PRIMARY,date_lance 	PRIMARY 	4 		task.idEnvoi 		1 	Using where
    1 	SIMPLE 		messages 	eq_ref 	PRIMARY 		PRIMARY 	4 		envois.idMessage 	1 	 
    1 	SIMPLE 		sites 		eq_ref 	PRIMARY 		PRIMARY 	4 		messages.idSite 	1
    INDEX sur la table task
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Nom de l'index 	Type 		Cardinalité 		Champ
    PRIMARY 		PRIMARY 	741565  	 	id
    idEnvoi 		INDEX 	5  		 	idEnvoi
    Je ne suis pas trés familier avec l'EXPLAIN mais,
    ce que je ne comprend pas c'est que j'ai l'impression que la clé idEnvoi (index sur la table task) n'est pas utilisée, et que toute la table est balayée.

    Est-ce que vous avez une idée ?
    Merci pour votre aide.

  2. #2
    Membre éprouvé
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2011
    Messages
    55
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2011
    Messages : 55
    Par défaut
    Bonjour,

    Quels sont les types de données des différents IdEnvoi ??

    As tu retiré les ORDER by pour faire explain sans eux ?

  3. #3
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2011
    Messages : 25
    Par défaut
    Bonjour,

    Les champs id sont en int(9).

    J'ai déjà testé sans order by, le résultat est identique.

    Sur la table task j'ai ajouté un index id,idEnvoi et idEnvoi,id.
    Il me prend le idEnvoi,id en possible key mais ne l'utilise pas.

    J'ai tenté le force index, pas de changement, il l'utilise pas.

    Est-ce que vous pouvez me confirmer que je lis bien l'explain et qu'il balaye bien toute la table task, alors que l'utilisation d'un index devrait réduire cela ?
    Au pire je m'attendais a ce qu'il lise 150.000 enregistrement (le nombre de task avec envois.id = task.idEnvoi ) et j'esperais que le limite reduirait encore cela ...

    Comment est-ce que je peux m'assurer que les index sont bien construit ?

  4. #4
    Expert éminent
    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 818
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur d'études en informatique
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2006
    Messages : 16 818
    Billets dans le blog
    14
    Par défaut
    Un peu de bonnes pratiques...

    1) Évite la guerre des étoiles !

    2) Les jointures s'écrivent depuis 1992 avec l'opérateur JOIN

    3) Quand il y a plus d'une table dans une requête, celle-ci est plus facile à lire quand on utilise des alias.

    4) Indenter correctement le code permet aussi de mieux comprendre la requête.

    Voici votre requête récrite :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    SELECT -- les colonnes nécessaires et pas étoile !
    FROM envois e
    INNER JOIN task t ON e.id = t.idEnvoi
    INNER JOIN messages m ON e.idMessage = m.id
    	INNER JOIN sites s ON m.idSite = s.id
    WHERE e.idEnvoyeur = 1  
    	AND 
    	( 
    		e.STATUS = 'ENV' 
    		OR 
    		(
    			e.STATUS = 'PRG' 
    			AND e.date_lance <= CURRENT_TIMESTAMP
    		)
    	)
    ORDER BY envois.priority DESC, envois.id ASC, task.id ASC
    LIMIT 0,150
    Toutes les conditions de restriction (ce qu'il y a dans WHERE) portent sur la table "envois".
    Y a t-il besoin dans le SELECT de colonnes provenant des autres tables ou certaines jointures sont-elles inutiles ?

    Des index sur envois.idEnvoyeur, sur envois.STATUS et sur envois.date_lance seraient peut-être utiles pour ne pas balayer toute la table envois.

    Il faut également que les colonnes messages.idSite, envois.idMessage et task.idEnvoi soient indexées puisqu'elles font fonction de clé étrangère, même si les tables sont peut-être en MyISAM et que les contraintes de clés étrangères ne sont pas utilisées.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole, en retraite... mais toujours Autoentrepreneur à l'occasion.
    Mon ancien blog sur la conception des BDD, le langage SQL, le PHP... et mon nouveau blog sur les mêmes sujets.
    « Ce que l'on conçoit bien s'énonce clairement, et les mots pour le dire arrivent aisément ». (Nicolas Boileau)
    À la maison comme au bureau, j'utilise la suite Linux Mageïa !

  5. #5
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2011
    Messages : 25
    Par défaut
    Merci pour ton aide CinePhil

    1) J'adore la guerre des étoiles ... le film, mais dans ce cas précis je ne récupère que les champs dont j'ai besoin.J'ai mis * pour vous alléger la lecture de la requête.
    J'ai fait plusieurs tests en modifiant les champs du select, au pire en ne gardant que le task.id, cela ne change rien.

    2) J'ai toujours écrit mes requêtes avec "=".Surement une habitude de 'vieux' Coboliste, ou la quasi totalité des programmes sont bien plus vieux que 1992 ..
    J'ai gardé cette sale habitude par la suite, mais promis je vais faire un effort.

    3-4)Mea culpa, c'est codé 'proprement', j'ai un peu modifier ça pour le mettre sur le forum pensant que ce serait plus clair .. erreur d'appreciation.

    Les tables envois, messages et sites contiennent un centaine de ligne au maximum chacune, l’accès ne pose pas de problème à priori.
    Seule date_lance dans la table envois est indexé.

    Les tables sont bien en MyISAM, sans contraintes de clé étrangère.

    Je vais essayer ta requête et voir ce que ça donne.
    Encore merci pour ton aide.

  6. #6
    Membre averti
    Homme Profil pro
    Inscrit en
    Juin 2011
    Messages
    25
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Belgique

    Informations forums :
    Inscription : Juin 2011
    Messages : 25
    Par défaut
    Pas de modification sur l'explain avec la nouvelle requête.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    SELECT
    t.id as idTask, t.uniqueId as uniqueId, t.flag as flag,
    e.fichier as fichier, e.id as idEnvoi,  e.priority as priority, e.status as status, 
    s.id as idSite, s.txt as txtSite,
    m.id as idMsg, m.txt as txtMsg
     
    FROM envois e
    INNER JOIN task t ON e.id = t.idEnvoi
    INNER JOIN messages m ON e.idMessage = m.id
    	INNER JOIN sites s ON m.idSite = s.id
    WHERE e.idEnvoyeur = 1  
    	AND 
    	( 
    		e.STATUS = 'ENV' 
    		OR 
    		(
    			e.STATUS = 'PRG' 
    			AND e.date_lance <= CURRENT_TIMESTAMP
    		)
    	)
    ORDER BY e.priority DESC, e.id ASC, t.id ASC
    LIMIT 0,150

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Access] Optimisation performance requête - Index
    Par fdraven dans le forum Access
    Réponses: 11
    Dernier message: 12/08/2005, 14h30
  2. Optimisation de requête avec Tkprof
    Par stingrayjo dans le forum Oracle
    Réponses: 3
    Dernier message: 04/07/2005, 09h50
  3. Optimiser une requête SQL d'un moteur de recherche
    Par kibodio dans le forum Langage SQL
    Réponses: 2
    Dernier message: 06/03/2005, 20h55
  4. optimisation des requêtes
    Par yech dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 21/09/2004, 19h03
  5. Optimisation de requête
    Par olivierN dans le forum SQL
    Réponses: 10
    Dernier message: 16/12/2003, 10h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo