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 :

Problème performance sous requête MySQL


Sujet :

Requêtes MySQL

  1. #1
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut Problème performance sous requête MySQL
    Bonjour,

    Je rencontre des soucis de performance avec des sous-requêtes en MySQL 5 et j'avoue ne pas bien comprendre pourquoi. J'ai plusieurs requêtes, qui exécutées séparément sont très rapides mais dont l'imbrication fait chuter les performances.

    Les requêtes séparées:
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    select distinct f.to_icao from flight f, airline a where (f.airline_id = a.id or f.suboperator_id = a.id) and a.name = 'Air Nostrum'
    0.047sec
     
    to_icao
    LEMD
    LEAL
    LEVC
    GCRR
    LEPP
    GCFV
    LEGR
    LEPA
    EDDM
    LEZL
    LIPZ
    LOWW
    LGAV
    LEMG
    LEAS
    LPPT
    LSZH
    LIRF
    LSGG
    EDDF
    LIMC
    LFPO
    EDDL
    LEVX
    LEJR
    LEST
    LEIB
    GCXO
    GCLP
    EIDW
    LELC
    GEML
    LEAM
    LEBZ
    LEBL
    LESO
    LEBB
    LECO
    GMMX
    GMTT
    GMME
    LEXJ
    LELN
    LEMH
    EGPF
    EGCC
    LFLC
    LEVD
    LFRS
    LFBD
    LIRN
    LEDA
    LIPE
    LFST
    LESA
    LFLL
    LEBG
    LPPR
    LFMN
    LFBO
    LIMF
    LIRP
    LFMT
    LIMJ
    LFML
    Requête suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    select m.station, 
    	   count(distinct m.id) as Nb_Metar,
            (select count(distinct m5.id) from metar m5, cloud c5, visibility v5 where m.station = m5.station and m5.id = c5.metar_id and m5.id = v5.metar_id and ((c5.amount = 'BKN' and c5.height < 600) or v5.distance < 3200)) as Cloud_Inf_600_OR_Vis_Inf_3200,
            (select count(distinct m6.id) from metar m6, cloud c6, visibility v6 where m.station = m6.station and m6.id = c6.metar_id and m6.id = v6.metar_id and ((c6.amount = 'BKN' and c6.height < 250) or v6.distance < 900)) as Cloud_Inf_250_OR_Vis_Inf_900
    from metar m
    where m.station in ('LEMD','LEAL','LEVC','GCRR','LEPP','GCFV','LEGR','LEPA','EDDM','LEZL','LIPZ','LOWW','LGAV',
    'LEMG','LEAS','LPPT','LSZH','LIRF','LSGG','EDDF','LIMC','LFPO','EDDL','LEVX','LEJR','LEST','LEIB','GCXO','GCLP',
    'EIDW','LELC','GEML','LEAM','LEBZ','LEBL','LESO','LEBB','LECO','GMMX','GMTT','GMME','LEXJ','LELN','LEMH','EGPF',
    'EGCC','LFLC','LEVD','LFRS','LFBD','LIRN','LEDA','LIPE','LFST','LESA','LFLL','LEBG','LPPR','LFMN','LFBO','LIMF','LIRP','LFMT','LIMJ','LFML')
    group by m.station
    35.906sec
    Sachant que j'ai des index sur metar.station, airline.id, flight.to_icao, flight.airline_id, flight.suboperator_id

    En regroupant le tout cela donne ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select m.station, 
    	   count(distinct m.id) as Nb_Metar,
            (select count(distinct m5.id) from metar m5, cloud c5, visibility v5 where m.station = m5.station and m5.id = c5.metar_id and m5.id = v5.metar_id and ((c5.amount = 'BKN' and c5.height < 600) or v5.distance < 3200)) as Cloud_Inf_600_OR_Vis_Inf_3200,
            (select count(distinct m6.id) from metar m6, cloud c6, visibility v6 where m.station = m6.station and m6.id = c6.metar_id and m6.id = v6.metar_id and ((c6.amount = 'BKN' and c6.height < 250) or v6.distance < 900)) as Cloud_Inf_250_OR_Vis_Inf_900
    from metar m
    where m.station in (select distinct f.to_icao from flight f, airline a where (f.airline_id = a.id or f.suboperator_id = a.id) and a.name = 'Air Nostrum')
    group by m.station
    Pas de résultats après plus de 2 minutes d'attente alors que je m'attendais à ce que le temps des deux requêtes précédentes s'additionne.

    J'ai essayé aussi par jointure sans succès non plus:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    select m.station, 
    	   count(distinct m.id) as Nb_Metar,
            (select count(distinct m5.id) from metar m5, cloud c5, visibility v5 where m.station = m5.station and m5.id = c5.metar_id and m5.id = v5.metar_id and ((c5.amount = 'BKN' and c5.height < 600) or v5.distance < 3200)) as Cloud_Inf_600_OR_Vis_Inf_3200,
            (select count(distinct m6.id) from metar m6, cloud c6, visibility v6 where m.station = m6.station and m6.id = c6.metar_id and m6.id = v6.metar_id and ((c6.amount = 'BKN' and c6.height < 250) or v6.distance < 900)) as Cloud_Inf_250_OR_Vis_Inf_900
    from metar m, flight f, airline a
    where m.station = f.to_icao and (f.airline_id = a.id or f.suboperator_id = a.id) and a.name = 'Air Nostrum'
    group by m.station
    Est ce que quelqu'un a déjà rencontré ce cas de figure? Je souhaiterais n'avoir à faire qu'une seule requête.

    En vous remerciant

  2. #2
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Les requêtes imbriquées dans le SELECT, c'est sûr que c'est pas top !

    Les jointures vieilles de 20 ans non plus d'ailleurs !

    Tu peux expliquer ce qu'est censée faire la requête ?

    EDIT :
    Si j'interprète correctement la partie des SELECTs imbriqués, tu cherches à compter le nombre de metar par station selon deux conditions différentes.

    Je pense alors que cette requête répond au besoin :
    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
    23
    24
    25
    26
    SELECT m.station, 
    	SUM
    	(
    		CASE
    			WHEN (c.amount = 'BKN' AND c.height < 600) 
    					OR v.distance < 3200
    				THEN 1
    			ELSE 0
    		END
    	) AS Cloud_Inf_600_OR_Vis_Inf_3200,
    	SUM
    	(
    		CASE
    			WHEN (c.amount = 'BKN' AND c.height < 250) 
    					OR v.distance < 900
    				THEN 1
    			ELSE 0
    		END
    	) AS Cloud_Inf_250_OR_Vis_Inf_900
    FROM metar m
    INNER JOIN cloud c ON m.id = c.metar_id
    INNER JOIN visibility v ON m.id = v.metar_id
    INNER JOIN flight f ON m.station = f.to_icao
    	INNER JOIN airline a ON f.airline_id = a.id OR f.suboperator_id = a.id
    WHERE a.name = 'Air Nostrum'
    GROUP BY m.station
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  3. #3
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    En gros, il s'agit d'analyser des données météo sur des aéroports et de comptabiliser le nombre de relevés qui répondent à certains critères de visibilité et de hauteur de couches nuageuse.

    La jointure ou sous sélection permet de n'effectuer ce calcul statistique que sur les aéroports de destination d'une compagnie aérienne donnée. Ici, Air Nostrum.

    Je ne peux me permettre de faire l'analyse sur toutes les stations météo car le volume de données est conséquent. La requête qui prend trente secondes travaille déjà sur 4 millions de lignes.

    Voici un exemple de résultats:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Station NbMetar Cloud_Inf_600_OR_Vis_Inf_3200 Cloud_Inf_250_OR_Vis_Inf_900
    EDDF	34826	1432	                                           646
    EDDL	34824	1416	                                           242
    EDDM	34826	4304	                                           1706
    EGCC	34350	1408	                                           348
    EGPF	17369	812	                                           286
    EIDW	17377	422	                                           122
    GCFV	12722	11	                                           0
    GCLP	17376	54	                                           1
    ...     ...	...   	                                           ...

  4. #4
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    J'ai édité ma réponse avec une proposition de requête.
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    Pas mieux...

    J'ai fait tourner ta requête pendant plus de 3 minutes sans résultat. De plus, il me manque le décompte total dans la requête que tu as écrite car au final, le but est d'obtenir un ratio par rapport au nombre total de relevés par station.

  6. #6
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    C'est bien la sous requête select qui pause problème. Je me suis inspiré de ta méthode avec la fonction sum et case pour tester le résultat.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    select m.station, 
    	   count(distinct m.id) as Nb_Metar,
    	   SUM(CASE WHEN (c.amount = 'BKN' AND c.height < 600) OR v.distance < 3200 THEN 1 ELSE 0 END) AS Cloud_Inf_600_OR_Vis_Inf_3200,
    	   SUM(CASE WHEN (c.amount = 'BKN' AND c.height < 250) OR v.distance < 900 THEN 1 ELSE 0 END) AS Cloud_Inf_250_OR_Vis_Inf_900,
            (select count(distinct m5.id) from metar m5, cloud c5, visibility v5 where m.station = m5.station and m5.id = c5.metar_id and m5.id = v5.metar_id and ((c5.amount = 'BKN' and c5.height < 600) or v5.distance < 3200)) as Cloud_Inf_600_OR_Vis_Inf_3200,
            (select count(distinct m6.id) from metar m6, cloud c6, visibility v6 where m.station = m6.station and m6.id = c6.metar_id and m6.id = v6.metar_id and ((c6.amount = 'BKN' and c6.height < 250) or v6.distance < 900)) as Cloud_Inf_250_OR_Vis_Inf_900
    from metar m
    LEFT OUTER JOIN cloud c on c.metar_id = m.id
    LEFT OUTER JOIN visibility v on v.metar_id = m.id
    where m.station = 'LEMD'
    group by m.station
    Et j'obtiens ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LEMD	17549	564	175	353	122
    Le problème c'est que j'ai plusieurs visibility et cloud par metar donc j'avais fait un select distinct pour ne pas comptabiliser un metar plusieurs fois. Du coup, l'utilisation du case ne me convient pas.

    Donc pour le moment, le mystère de la sous requête qui prend un temps infini reste entier.

    Si quelqu'un a une idée...

  7. #7
    Membre expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Points : 3 295
    Points
    3 295
    Billets dans le blog
    1
    Par défaut
    salut,

    as tu regardé avec un explain si tu avais pas un problème de régénération de ta sous-requêtes à chaque itération de ta requête principale?

    j'ai déjà vu ce bug qu'un type avait décrit ici sur le forum...

    la table temporaire (générée automatiquement en interne) correspondant à la sous-requête était refaite à chaque fois ce qui rendait le temps d'exécution prohibitif... visiblement un bug de mysql sur certains configurations de sous-requêtes...

    une solution, qui peut améliorer peut-être un peu si l'écriture en une seul requête ne va pas est d'utiliser une procédure stockée qui va:
    • générer une table temporaire grace à ta sous-requête dans le in
    • exécuter ta requête principale en utilisant un simple select sur la table temporaire


    après si tu as accès au paramétrages du serveur, tu peux aussi tenter d'augmenter un peu les valeurs de buffer pour les tables (et/ou celles pour les jointures)...
    soyons pensez à mettre quand votre problème est résolu ou à utiliser pour les réponses pertinentes...
    ne posez pas de problématique soi-disant simplifiée sur des problèmes que vous n'êtes pas capable de résoudre par respect pour ceux qui planchent dessus... sinon: et à utiliser pour insérer votre code...

  8. #8
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    J'ai fait un explain sur la requête suivante
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    explain select m.station, 
    	   count(distinct m.id) as Nb_Metar,
            (select count(distinct m5.id) from metar m5, cloud c5, visibility v5 where m.station = m5.station and m5.id = c5.metar_id and m5.id = v5.metar_id and ((c5.amount in ('BKN','OVC') and c5.height <= 600) or v5.distance <= 3200)) as Cloud_Inf_600_OR_Vis_Inf_3200,
            (select count(distinct m6.id) from metar m6, cloud c6, visibility v6 where m.station = m6.station and m6.id = c6.metar_id and m6.id = v6.metar_id and ((c6.amount in ('BKN','OVC') and c6.height <= 250) or v6.distance <= 900)) as Cloud_Inf_250_OR_Vis_Inf_900
    from metar m
    where m.station in (select f.to_icao from flight f, airline a where (f.airline_id = a.id or f.suboperator_id = a.id) and a.name = 'Air Nostrum' group by to_icao)
    group by m.station
    Et j'obtiens ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    id	select_type	        table	type	possible_keys	key	key_len	ref	rows	Extra
    1	PRIMARY	                m	index	(null)	station_idx	6	(null)	1003545	Using where; Using index
    4	DEPENDENT SUBQUERY	f	ALL	FK7D967090CD4E8828,FK7D967090932D8BC2	(null)	(null)	(null)	15978	Using temporary; Using filesort
    4	DEPENDENT SUBQUERY	a	ALL	PRIMARY	(null)	(null)	(null)	1298	Range checked for each record (index map: 0x1)
    3	DEPENDENT SUBQUERY	m6	ref	PRIMARY,station_idx	station_idx	6	func	55752	Using index
    3	DEPENDENT SUBQUERY	v6	ref	FKEA883F323C7A59EA	FKEA883F323C7A59EA	8	db.m6.id	1	
    3	DEPENDENT SUBQUERY	c6	ref	FK3E2EE153C7A59EA	FK3E2EE153C7A59EA	8	db.m6.id	1	Using where
    2	DEPENDENT SUBQUERY	m5	ref	PRIMARY,station_idx	station_idx	6	func	55752	Using index
    2	DEPENDENT SUBQUERY	v5	ref	FKEA883F323C7A59EA	FKEA883F323C7A59EA	8	db.m5.id	1	
    2	DEPENDENT SUBQUERY	c5	ref	FK3E2EE153C7A59EA	FK3E2EE153C7A59EA	8	db.m5.id	1	Using where
    Effectivement, d'après ce que j'ai compris du explain sur les tables f (flight) et airline (a) signifie bien que l'analyse est refaite pour chaque ligne alors que cela n'est pas nécessaire.

    Y a-t-il un moyen de forcer mySQL à ne pas faire cette analyse pour chaque ligne? Ce comportement par défaut est vraiment étrange.

    Sinon effectivement il faudra que je passe par une procédure stockée, mais si possible j'aimerai éviter.

  9. #9
    Membre expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Points : 3 295
    Points
    3 295
    Billets dans le blog
    1
    Par défaut
    non je ne crois pas que ce soit possible...

    comme je te l'ai dit la solution de la procédure est ce que le gars a du mettre en pratique comme je lui avais proposé car il n' a pas de paramètres qui permettent de toucher au comportement de l'optimiseur et de de la gestion sauf à forcer l'usage d'index ce qui n'est pas le problème ici...

    d'un autre coté, la procédure te permet d'avoir pas de grosse requête à passer et finalement ça peut te permettre de développer un api où tu sépare bien mysql du langage serveur que tu utilises pour gérer les résultats...

    donc tu y perd pas vraiment au final...

    par contre utilise l'écriture de jointure normalisée pour la sous requête, elle est plus lisible et surtout plus optimisée que l'autre...

    soyons pensez à mettre quand votre problème est résolu ou à utiliser pour les réponses pertinentes...
    ne posez pas de problématique soi-disant simplifiée sur des problèmes que vous n'êtes pas capable de résoudre par respect pour ceux qui planchent dessus... sinon: et à utiliser pour insérer votre code...

  10. #10
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    Merci pour le mot clé EXPLAIN, je ne connaissais pas. Il semble que ce qui pose problème à mySQL c'est la clause OR dans la sous requête.

    En décomposant en deux sous requêtes ça marche:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    select m.station, 
    	   count(distinct m.id) as Nb_Metar,
            (select count(distinct m5.id) from metar m5, cloud c5, visibility v5 where m.station = m5.station and m5.id = c5.metar_id and m5.id = v5.metar_id and ((c5.amount in ('BKN','OVC') and c5.height <= 600) or v5.distance <= 3200)) as Cloud_Inf_600_OR_Vis_Inf_3200,
            (select count(distinct m6.id) from metar m6, cloud c6, visibility v6 where m.station = m6.station and m6.id = c6.metar_id and m6.id = v6.metar_id and ((c6.amount in ('BKN','OVC') and c6.height <= 250) or v6.distance <= 900)) as Cloud_Inf_250_OR_Vis_Inf_900
    from metar m
    where m.station in (select distinct f.to_icao from airline a, flight f where a.name = 'Air Nostrum' and a.id = f.suboperator_id)
    or m.station in (select distinct f2.to_icao from airline a2, flight f2 where a2.name = 'Air Nostrum' and a2.id = f2.airline_id)
    group by m.station
    Le explain me donne ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    id	select_type	      table	type	possible_keys	key	key_len	ref	rows	Extra
    1	PRIMARY	                m	index	(null)	station_idx	6	(null)	1003545	Using where; Using index
    5	DEPENDENT SUBQUERY	f2	ref	FK7D967090CD4E8828,FK7D967090DBC27E05	FK7D967090DBC27E05	6	func	8	Using temporary
    5	DEPENDENT SUBQUERY	a2	eq_ref	PRIMARY	PRIMARY	8	db.f2.airline_id	1	Using where
    4	DEPENDENT SUBQUERY	f	ref	FK7D967090DBC27E05,FK7D967090932D8BC2	FK7D967090DBC27E05	6	func	8	Using temporary
    4	DEPENDENT SUBQUERY	a	eq_ref	PRIMARY	PRIMARY	8	db.f.subOperator_id	1	Using where
    3	DEPENDENT SUBQUERY	m6	ref	PRIMARY,station_idx	station_idx	6	func	55752	Using index
    3	DEPENDENT SUBQUERY	v6	ref	FKEA883F323C7A59EA	FKEA883F323C7A59EA	8	db.m6.id	1	
    3	DEPENDENT SUBQUERY	c6	ref	FK3E2EE153C7A59EA	FK3E2EE153C7A59EA	8	db.m6.id	1	Using where
    2	DEPENDENT SUBQUERY	m5	ref	PRIMARY,station_idx	station_idx	6	func	55752	Using index
    2	DEPENDENT SUBQUERY	v5	ref	FKEA883F323C7A59EA	FKEA883F323C7A59EA	8	db.m5.id	1	
    2	DEPENDENT SUBQUERY	c5	ref	FK3E2EE153C7A59EA	FK3E2EE153C7A59EA	8	db.m5.id	1	Using where
    Et j'ai un temps de réponse de 92sec contre 35sec sans sous requête. Je ne comprends pas d'où vient cette perte de temps. C'est déjà plus acceptable qu'avant par contre.

  11. #11
    Membre expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Points : 3 295
    Points
    3 295
    Billets dans le blog
    1
    Par défaut
    ah oui, déjà nomme tes indexes si tu peux c'est plus pratique, enfin si tu as accès à cette possibilité...

    le or fait qu'aucun index n'est choisi sur les conditions qu'il réunit car pour mysql comme ça peut être l'une ou l'autre valeur qui rentre en jeu alors l'utilisation de l'index sur l'une ou l'autre condition ne permet de garantir la restriction sur les lignes...

    bienvenu dans le monde merveilleux des indexes et de l'optimiseur mysql

    pour les utiliser tu fais une union entre 2 requêtes portant chacune sur une des 2 conditions et là tu retrouveras des temps bien meilleurs normalement...

    et écrit ta requête avec une syntaxe de jointure normalisée
    soyons pensez à mettre quand votre problème est résolu ou à utiliser pour les réponses pertinentes...
    ne posez pas de problématique soi-disant simplifiée sur des problèmes que vous n'êtes pas capable de résoudre par respect pour ceux qui planchent dessus... sinon: et à utiliser pour insérer votre code...

  12. #12
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    Merci pour le conseil sur les jointures. ça m'a permis de me rendre compte d'une erreur sur ma requête qui doit en fait utiliser des Left outer join pour analyser toutes les données.

    Au niveau des performances par contre, ça a eu tendance à chuter mais cela parait normal étant donné que j'ai plus de données à traiter.

  13. #13
    Membre expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Points : 3 295
    Points
    3 295
    Billets dans le blog
    1
    Par défaut
    oui c'est pas forcément choquant...

    mais c'est pour ça qu'on arrête pas de vous dire à tous de ne plus utiliser une pauvre syntaxe obsolète depuis près de 20 ans...



    et si tu as un projet où tu crées ou peux modifier les tables, nomme tes contraintes, clés primaires et étrangères, etc...

    ça facilite la lecture dans un explain par exemple...

    pour les trucs genre explain, benchmark, etc... lis la doc mysql qui les explique plus en détails...

    une bonne lecture aussi c'est les section sur l'utilisation des indexes et optimisation...

    et pense à bien regarder la doc de la version exacte de mysql car parfois tu peux avoir des différences et google ne donne souvent que celle de la version 5 et pas les suivantes sauf si on précise...
    soyons pensez à mettre quand votre problème est résolu ou à utiliser pour les réponses pertinentes...
    ne posez pas de problématique soi-disant simplifiée sur des problèmes que vous n'êtes pas capable de résoudre par respect pour ceux qui planchent dessus... sinon: et à utiliser pour insérer votre code...

  14. #14
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 799
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    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 799
    Points : 34 031
    Points
    34 031
    Billets dans le blog
    14
    Par défaut
    Essaie cette 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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    SELECT m.station,
    	count(DISTINCT m.id) AS Nb_Metar,
    	t1.Cloud_Inf_600_OR_Vis_Inf_3200,
    	t2.Cloud_Inf_250_OR_Vis_Inf_900
    FROM metar m
    INNER JOIN flight f ON m.station = f.to_icao
    	INNER JOIN airline a ON f.airline_id = a.id OR f.suboperator_id = a.id
    INNER JOIN 
    (
    	SELECT m5.station, count(DISTINCT m5.id) AS Cloud_Inf_600_OR_Vis_Inf_3200
    	FROM metar m5 
    	INNER JOIN cloud c5 ON m5.id = c5.metar_id
    	INNER JOIN visibility v5 ON m5.id = v5.metar_id
    	WHERE 
    	(
    		c5.amount = 'BKN' 
    		AND c5.height < 600
    	) 
    		OR v5.distance < 3200
    	GROUP BY m5.station
    ) t1 ON m.station = t1.station
    INNER JOIN
    (
    	SELECT m6.station, count(DISTINCT m6.id) AS Cloud_Inf_250_OR_Vis_Inf_900
    	FROM metar m6
    	INNER JOIN cloud c6 ON m6.id = c6.metar_id
    	INNER JOIN visibility v6 ON m6.id = v6.metar_id
    	WHERE 
    	(
    		c6.amount = 'BKN' 
    		AND c6.height < 250
    	) 
    		OR v6.distance < 900
    	GROUP BY m6.station
    ) t2 ON m.station = t2.station
    WHERE a.name = 'Air Nostrum'
    GROUP BY m.station
    Philippe Leménager. Ingénieur d'étude à l'École Nationale Supérieure de Formation de l'Enseignement Agricole. Autoentrepreneur.
    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 !

  15. #15
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    Elle a l'air sympa cette requête

    En faisant juste un explain dessus j'ai 6 ALL. Je l'ai tout de même lancé mais sans succès.

    Pour le nommage des indexes et FK je suis tout à fait de votre avis. Pour le moment, j'ai généré le schéma à partir de JPA et effectivement les noms qu'il génère ne sont pas très parlant. Il faudra que je reprenne à la main. Je n'ai pas trouvé comment faire pour spécifier le nom de la FK par annotation.

    En ce qui concerne l'union pour éviter la clause OR je serais intéressé par la requête. Je ne suis pas familier avec cette clause.

    Merci

    EDIT:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    select m.station, 
    	   count(distinct m.id) as Nb_Metar,
            (select count(distinct m5.id) from metar m5, cloud c5, visibility v5 where m.station = m5.station and m5.id = c5.metar_id and m5.id = v5.metar_id and ((c5.amount in ('BKN','OVC') and c5.height <= 600) or v5.distance <= 3200)) as Cloud_Inf_600_OR_Vis_Inf_3200,
            (select count(distinct m6.id) from metar m6, cloud c6, visibility v6 where m.station = m6.station and m6.id = c6.metar_id and m6.id = v6.metar_id and ((c6.amount in ('BKN','OVC') and c6.height <= 250) or v6.distance <= 900)) as Cloud_Inf_250_OR_Vis_Inf_900
    from metar m
    where m.station in (
            select distinct f.to_icao from flight f inner join airline a on f.airline_id = a.id where a.name = 'Air Nostrum'
            union
            select distinct f.to_icao from flight f inner join airline a on f.suboperator_id = a.id where a.name = 'Air Nostrum')
    group by m.station
    Mais l'union est réexécutée pour chaque ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
    1	PRIMARY	m	index	(null)	station_idx	6	(null)	994473	Using where; Using index
    4	DEPENDENT SUBQUERY	f	ref	FK7D967090CD4E8828,FK7D967090DBC27E05	FK7D967090DBC27E05	6	func	9	Using temporary
    4	DEPENDENT SUBQUERY	a	eq_ref	PRIMARY	PRIMARY	8	db.f.airline_id	1	Using where
    5	DEPENDENT UNION	f	ref	FK7D967090DBC27E05,FK7D967090932D8BC2	FK7D967090DBC27E05	6	func	9	Using temporary
    5	DEPENDENT UNION	a	eq_ref	PRIMARY	PRIMARY	8	db.f.subOperator_id	1	Using where
    (null)	UNION RESULT	<union4,5>	ALL	(null)	(null)	(null)	(null)	(null)	
    3	DEPENDENT SUBQUERY	m6	ref	PRIMARY,station_idx	station_idx	6	func	55248	Using index
    3	DEPENDENT SUBQUERY	v6	ref	FKEA883F323C7A59EA	FKEA883F323C7A59EA	8	db.m6.id	1	
    3	DEPENDENT SUBQUERY	c6	ref	FK3E2EE153C7A59EA	FK3E2EE153C7A59EA	8	db.m6.id	1	Using where
    2	DEPENDENT SUBQUERY	m5	ref	PRIMARY,station_idx	station_idx	6	func	55248	Using index
    2	DEPENDENT SUBQUERY	v5	ref	FKEA883F323C7A59EA	FKEA883F323C7A59EA	8	db.m5.id	1	
    2	DEPENDENT SUBQUERY	c5	ref	FK3E2EE153C7A59EA	FK3E2EE153C7A59EA	8	db.m5.id	1	Using where
    Pas de réponse après 2 minutes d'attente

  16. #16
    Membre expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Points : 3 295
    Points
    3 295
    Billets dans le blog
    1
    Par défaut
    à mon avis la solution de cinephil marche bien mais c'est juste un problème de performance qui bloque...

    tu es un peu arrivé aux limites de ce que peut supporter mysql avec une configuration standard...

    comme je te disais si tu as accès à my.cnf de ton serveur mysql alors tente d'augmenter les buffers pour les tables et ceux pour les jointures... je crois que tu as aussi une limite de temps d'exécution coté mysql...

    comme l'attaque frontale en une requête ne passe pas c'est pour ça que je t'ai proposé la solution de le faire en plusieurs fois...

    pareil ce qui te pourrit tes performances c'est que tu as des or qui empêchent que distance et height puisse avoir un index utilisable... une solution à creuser serait de faire une union sur la recherche sur la distance et sur height... avec 2 index multi-colonnes prenant l'un puis l'autre...bien choisis
    soyons pensez à mettre quand votre problème est résolu ou à utiliser pour les réponses pertinentes...
    ne posez pas de problématique soi-disant simplifiée sur des problèmes que vous n'êtes pas capable de résoudre par respect pour ceux qui planchent dessus... sinon: et à utiliser pour insérer votre code...

  17. #17
    Futur Membre du Club
    Inscrit en
    Juin 2010
    Messages
    15
    Détails du profil
    Informations forums :
    Inscription : Juin 2010
    Messages : 15
    Points : 6
    Points
    6
    Par défaut
    J'utilise une base mySQL embarquée avec le connector mxj. Je ne trouve pas le .cnf dans le dossier database généré. De même, je n'ai pas l'exe mysqldump qui me serait bien pratique pour faire un dump complet de ma base et mon schéma.

    Je suppose que la version embarquable est plus light. Le soucis, c'est que je ne peux rien installer sur mon poste (pas admin) et que si je fais une demande j'en ai pour 3 mois... Mais pour le moment, il s'agit juste d'un prototypage d'une base qui sera peut être portée sur oracle si elle doit être déployée sur un serveur.

    Merci pour les conseils

  18. #18
    Membre expert
    Avatar de ericd69
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Avril 2011
    Messages
    1 919
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Avril 2011
    Messages : 1 919
    Points : 3 295
    Points
    3 295
    Billets dans le blog
    1
    Par défaut
    faudra revoir les requêtes sous oracle, les performances étant bien différentes...

    sinon essaye de faire les unions sur distance et height avec un index sur l'un et un index sur l'autre...

    ça devrait accélérer puisqu'on vire le or et qu'on peut alors faire jouer les indexes...
    soyons pensez à mettre quand votre problème est résolu ou à utiliser pour les réponses pertinentes...
    ne posez pas de problématique soi-disant simplifiée sur des problèmes que vous n'êtes pas capable de résoudre par respect pour ceux qui planchent dessus... sinon: et à utiliser pour insérer votre code...

Discussions similaires

  1. Problème de sous requête (retour d'une seule valeur)
    Par ero-sennin dans le forum Requêtes
    Réponses: 1
    Dernier message: 14/06/2006, 11h12
  2. Problème de sous-requêtes
    Par R'SKaP dans le forum Langage SQL
    Réponses: 6
    Dernier message: 24/05/2006, 19h39
  3. Problème de sous requête
    Par espadon1 dans le forum Requêtes
    Réponses: 4
    Dernier message: 11/05/2006, 15h20
  4. Problème de sous requête
    Par Draiwn dans le forum Requêtes
    Réponses: 8
    Dernier message: 16/11/2005, 01h43

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