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 :

Requêtes imbriquées lentes [MySQL-5.5]


Sujet :

Requêtes MySQL

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2018
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2018
    Messages : 12
    Points : 7
    Points
    7
    Par défaut Requêtes imbriquées lentes
    Bonjour à tous,

    Je rencontre un problème de performance sur une requête comportant des sous requêtes imbriquées. Ma requête s'exécute bien en local (avec Mysql 5.7) avec en moyenne un traitement en 1,5 sec. Par contre sur mon serveur de production (en Mysql 5.5) cette requête s'exécute en minimum 30 sec. !

    Cela me semble bizarre qu'il y ait autant de différence uniquement entre Mysql 5.7 et 5.5

    Voici ma 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
     
    SELECT p.*, 
        	(
    		SELECT MIN(pr.price_value)
    		FROM price pr
    		INNER JOIN product2url pu ON pu.url_id = pr.url_id
    		WHERE pu.product_id = p.product_id AND DATE_FORMAT(pr.price_date_add, "%Y-%m-%d") = 		
    		(
    			SELECT MAX(DATE_FORMAT(pr2.price_date_add, "%Y-%m-%d")) as dateformat 
    			FROM price pr2 
    			INNER JOIN product2url pu2 ON pu2.url_id = pr2.url_id 
    			WHERE pu2.product_id = p.product_id AND pr2.price_date_add > '2018-11-01 00:00:00'
    		)
    	) AS minprice
    FROM product p LIMIT 100
    Voici mes tables :
    Nom : bdd.png
Affichages : 234
Taille : 11,9 Ko

    Les champs products_id et url_id sont mis en index des tables les contenant.

    Je précise que la table price comporte plus de 400 000 lignes ce qui rend cette requête lourde (et donc potentielement lente)

    Pour résumer cette requête veut récupérer tous les produits de ma table product et pour chaque produit prendre le prix le plus bas de la date la plus récente dans la table price.

    D'après mes tests c'est la sous requête suivante qui rend le tout lent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    SELECT MAX(DATE_FORMAT(pr2.price_date_add, "%Y-%m-%d")) as dateformat 
    FROM price pr2 
    INNER JOIN product2url pu2 ON pu2.url_id = pr2.url_id 
    WHERE pu2.product_id = p.product_id AND pr2.price_date_add > '2018-11-01 00:00:00'
    Je pense que le WHERE pr2.price_date_add > '2018-11-01 00:00:00' n'est pas interprété ou pris en compte en Mysql 5.5 ce qui me parait bizarre.

    Auriez vous une idée de pourquoi cette lenteur d'exécution en Mysql 5.5 et pas en 5.7 ?

    Merci à tous.

  2. #2
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2018
    Messages
    12
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Pyrénées Orientales (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2018
    Messages : 12
    Points : 7
    Points
    7
    Par défaut
    J'ai trouvé une solution

    En fait j'ai fait un SELECT supplémentaire dans le FROM de ma sous requête.
    Ca donne :

    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
     
    SELECT p.*,
    	(
    		SELECT MIN(pr.price_value)
    		FROM price pr
    		INNER JOIN product2url pu ON pu.url_id = pr.url_id
    		WHERE pu.product_id = p.product_id AND DATE_FORMAT(pr.price_date_add, "%Y-%m-%d") = 		
    		(
    			SELECT MAX(DATE_FORMAT(maxdate.price_date_add, "%Y-%m-%d")) as dateformat 
    			FROM 
    				(
    					SELECT pr3.price_date_add 
    					FROM price pr3 
    					INNER JOIN product2url pu2 ON pu2.url_id = pr3.url_id
    					WHERE pr3.price_date_add > '2018-11-01 00:00:00'
     
    				) AS maxdate
    		)
    	) AS minprice
    FROM product p LIMIT 10
    Du coup, le SELECT que je fait dans le FROM me permet de ne faire une recherche que sur un nombre restreints de résultats ce qui accélère considérablement le process.

    Par contre je ne comprend toujours pas pourquoi cette différence de perf entre Mysql 5.5 et 5.7.

  3. #3
    Expert éminent sénior
    Homme Profil pro
    Responsable Données
    Inscrit en
    Janvier 2009
    Messages
    5 198
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Responsable Données

    Informations forums :
    Inscription : Janvier 2009
    Messages : 5 198
    Points : 12 774
    Points
    12 774
    Par défaut
    Bonjour,
    Je vois une grosse différence entre la première requête (du premier message), et celle du deuxième message: la sous-requête est corrélée dans la première, et pas dans la seconde:
    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
     
    SELECT p.*, 
        	(
    		SELECT MIN(pr.price_value)
    		FROM price pr
    		INNER JOIN product2url pu ON pu.url_id = pr.url_id
    		WHERE pu.product_id = p.product_id AND DATE_FORMAT(pr.price_date_add, "%Y-%m-%d") = 		
    		(
    			SELECT MAX(DATE_FORMAT(pr2.price_date_add, "%Y-%m-%d")) as dateformat 
    			FROM price pr2 
    			INNER JOIN product2url pu2 ON pu2.url_id = pr2.url_id 
    			WHERE pu2.product_id = p.product_id <= ici, il y a un lien entre p et pu2
    			AND pr2.price_date_add > '2018-11-01 00:00:00'
    		)
    	) AS minprice
    FROM product p LIMIT 100
    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
     
    SELECT p.*,
    	(
    		SELECT MIN(pr.price_value)
    		FROM price pr
    		INNER JOIN product2url pu ON pu.url_id = pr.url_id
    		WHERE pu.product_id = p.product_id AND DATE_FORMAT(pr.price_date_add, "%Y-%m-%d") = 		
    		(
    			SELECT MAX(DATE_FORMAT(maxdate.price_date_add, "%Y-%m-%d")) as dateformat 
    			FROM 
    				(
    					SELECT pr3.price_date_add 
    					FROM price pr3 
    					INNER JOIN product2url pu2 ON pu2.url_id = pr3.url_id
    					WHERE pr3.price_date_add > '2018-11-01 00:00:00' <= le lien avec p n'existe plus
     
    				) AS maxdate
    		)
    	) AS minprice
    FROM product p LIMIT 10
    Parce qu'honnêtement je ne vois pas l'intérêt de passer par une sous-sous-requête ici.

    Tatayo.

    P.S. Je ne parle pas du limite qui passe de 100 à 10 (une faute de frappe j'imagine).

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

Discussions similaires

  1. Pb requête imbriquée
    Par ddams dans le forum Requêtes
    Réponses: 11
    Dernier message: 20/04/2004, 12h13
  2. [Requête] Faire une requête imbriquée?
    Par sekiryou dans le forum Requêtes
    Réponses: 2
    Dernier message: 17/01/2004, 22h52
  3. problème avec une requête imbriquée
    Par jaimepasteevy dans le forum Langage SQL
    Réponses: 13
    Dernier message: 05/12/2003, 10h29
  4. Requêtes imbriquées ?
    Par Ph. B. dans le forum XMLRAD
    Réponses: 7
    Dernier message: 06/05/2003, 13h19
  5. Requête imbriquée et indexes INTERBASE
    Par vadim dans le forum InterBase
    Réponses: 2
    Dernier message: 06/09/2002, 16h15

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