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

Langage SQL Discussion :

select imbriqué et performances


Sujet :

Langage SQL

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 52
    Points : 47
    Points
    47
    Par défaut select imbriqué et performances
    Bonjour,

    je bosse depuis longtemps avec mysql 3.23 et je ne pouvais pas appliquer ce que j'avais appris à l'école, je ne pouvais pas faire de sous-requêtes.

    Mes serveur utilisent de plus en plus mysql5, je fais quelques tests mais les résultats sont ... surprenants.

    Sur une table de 6 000 éléments, si je fais

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Select Id , max( DateTime ) 
    From V1s 
    group by Id;
    J'obtiens "8 rows in set (0.01 sec)"

    Si je me sers d'un résultat pour faire une requête, genre ce que je fais en php

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     Select Id , DateTime , V 
    from V1s 
    where ( Id , DateTime ) IN ( (3877 , '2010-07-07 15:57:12') , 
    (3878 , '2010-07-07 15:57:12') , 
    ( 3879 , '2010-07-07 15:57:11') ,
    (3881 , '2010-07-07 15:57:12'),
    (3882 , '2010-07-07 15:57:12'),
    (3883 , '2010-07-07 15:57:12'),
    ( 3884 , '2010-07-07 15:57:12'),
    ( 3890 , '2010-07-07 15:40:47')   ) ;
    J'obtiens "8 rows in set (0.02 sec)"

    Si maintenant je m'amuse à faire plutôt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     Select Id , DateTime , V 
    from V1s 
    where ( Id , DateTime ) IN ( 
                                 Select Id , max( DateTime ) 
                                 From V1s 
                                 group by Id  
                              ) ;
    Et là c'est le drame, ça me donne les même résultats mais en 2 minutes.

    Je pensais que les 2 façons de faire était équivalentes en interne, la deuxième permettant d'économiser une requête et plus propre à écrire.

    Où est-ce que je me trompe ?

  2. #2
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Et avec une jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT Id, DateTime, V 
      FROM V1s
           INNER JOIN
           (  SELECT Id, max(DateTime) as dtmax 
                FROM V1s 
            GROUP BY Id ) as SR
             ON SR.Id = V1s.Id
            AND SR.dtmax = V1s.DateTime;

  3. #3
    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 : 61
    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 048
    Points
    34 048
    Billets dans le blog
    14
    Par défaut
    La colonne DateTime (très mauvais nom car c'est un mot réservé SQL !) est-elle indexée ?

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 52
    Points : 47
    Points
    47
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Et avec une jointure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    SELECT Id, DateTime, V 
      FROM V1s
           INNER JOIN
           (  SELECT Id, max(DateTime) as dtmax 
                FROM V1s 
            GROUP BY Id ) as SR
             ON SR.Id = V1s.Id
            AND SR.dtmax = V1s.DateTime;
    Là c'est immédiat. Il ne mouline manifestement pas les données de la même manière ... C'est dommage, je préfèrerais l'autre syntaxe.

    Citation Envoyé par CinePhil Voir le message
    La colonne DateTime (très mauvais nom car c'est un mot réservé SQL !) est-elle indexée ?
    Il y avait une clef unique sur le couple ( Id,DateTime ). J'ai rajouté un index sur DateTime mais ça n'a pas amélioré le temps.
    ( bon en fait c'est beaucoup plus lent mais comme j'ai lancé un dist-upgrade sur ce pc de test je ne vais pas en tirer de conclusions hâtives ... )

  5. #5
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 453
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 453
    Points : 18 388
    Points
    18 388
    Par défaut
    Bien qu'il n'y ait pas de règle absolue, de manière générale il ressort que les jointures sont meilleures.
    C'est le but des SGBD, faire des jointures ensemblistes et non du procédural.

    Je ne connais pas assez MySQL, mais ce qui pourrait justifier le temps d'exécution trop élevé avec votre IN serait qu'il exécute la sous-requête à chaque ligne.

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 879
    Points : 53 057
    Points
    53 057
    Billets dans le blog
    6
    Par défaut
    C'est surtout que MySQL est connu pour être particulièrement mauvais en performances dans les sous requêtes !

    A +

  7. #7
    Membre du Club
    Profil pro
    Inscrit en
    Février 2005
    Messages
    52
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 52
    Points : 47
    Points
    47
    Par défaut
    Citation Envoyé par Waldar Voir le message
    Bien qu'il n'y ait pas de règle absolue, de manière générale il ressort que les jointures sont meilleures.
    C'est le but des SGBD, faire des jointures ensemblistes et non du procédural.

    Je ne connais pas assez MySQL, mais ce qui pourrait justifier le temps d'exécution trop élevé avec votre IN serait qu'il exécute la sous-requête à chaque ligne.
    Oui on dirait, ce qui explique le rapport 1 à 6000.

    Par contre je me suis rendu compte qu'on peut mettre des tuples dans le WHERE

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT V1s.Id, DateTime, V 
    FROM V1s , (  SELECT Id, max(DateTime) AS dtmax 
                FROM V1s 
            GROUP BY Id ) SR
            where ( SR.Id , SR.dtmax ) = ( V1s.Id , V1s.DateTime)
    Ça me parait plus facile à lire que des clauses WHERE à rallonge.

  8. #8
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 879
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 879
    Points : 53 057
    Points
    53 057
    Billets dans le blog
    6
    Par défaut
    C'est ce que l'on appelle le ROW VALUE CONSTRUCTOR.
    Lisez l'article que j'ai écrit à ce sujet : http://sqlpro.developpez.com/cours/sqlaz/select/#L8

    A +

Discussions similaires

  1. [INSERT][SELECT] insert avec un select imbriqué
    Par narmataru dans le forum SQL
    Réponses: 11
    Dernier message: 06/03/2013, 03h04
  2. [MySql] Pb de select imbriqué
    Par 12_darte_12 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 22/02/2006, 12h21
  3. [ SQL ] Faire un update avec un select imbriqué
    Par zozolh2 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 11/04/2005, 12h05
  4. le select imbriqué correlé
    Par Tanahjampea dans le forum Langage SQL
    Réponses: 3
    Dernier message: 21/05/2004, 09h49
  5. SYBASE SELECT imbriqué clause FROM
    Par Nicolas Martel dans le forum Sybase
    Réponses: 2
    Dernier message: 19/11/2003, 15h28

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