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 PostgreSQL Discussion :

Choix entre 2 requêtes : performance ?


Sujet :

Requêtes PostgreSQL

  1. #1
    Membre à l'essai
    Inscrit en
    Novembre 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 23
    Points : 16
    Points
    16
    Par défaut Choix entre 2 requêtes : performance ?
    Bonjour,

    Difficile de décrire dans le titre ma question.

    Voici le MCD utilisé pour créer ma bdd
    http://img137.imageshack.us/i/mcdp.png

    Voici les tables :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    personne (id_u, u_nom, p_prenom, p_tel1, p_tel2, p_email, p_datenais, p_lieunais, #couleur, #fruit, #legume)  
    liste (id_li, li_nom) 
    item (id_it, it_nom, #id_li)
    La table liste contient 3 lignes avec le nom des listes : "fruit", "légumes", "couleurs"
    La table item contient tous les items des listes, par ex "banane", "violet", "courgette".

    Les 3 colonnes couleur, fruit et legume de ma table personne sont des clés étrangères liées à la table item. Chaque personne a donc un unique fruit, un unique légume et une unique couleur

    Pour récupérer dans une requête des informations sur les clients, et récupérer les intitulés, j'ai 2 possibilités:

    Requête 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    SELECT
    u_nom, p_prenom,
    c.it_nom AS couleur,
    f.it_nom AS fruit,
    l.it_nom AS legume
    FROM personne p ,
    (item NATURAL JOIN liste) As c,
    (item f NATURAL JOIN liste) AS f,
    (item l NATURAL JOIN liste) AS l
    WHERE 
    p.couleur = c.id_it
    AND p.fruit = f.id_it
    AND p.legume = l.id_it
    Requête 2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    SELECT
    u_nom, p_prenom,
    (SELECT it_nom FROM item NATURAL JOIN liste WHERE id_it = p.couleur) AS couleur,
    (SELECT it_nom FROM item NATURAL JOIN liste WHERE id_it = p.fruit) AS fruit,
    (SELECT it_nom FROM item NATURAL JOIN liste WHERE id_it = p.legume) AS legume
    FROM personne p
    Je ne sais pas du tout laquelle est la mieux.

    * La première utilise 3 appels à la même table "item" (+jointure vers "liste") avec des alias différents et a besoin de 3 clauses WHERE
    Il est simple d'ajouter des clauses WHERE comme
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    AND c.it_nom LIKE 'bl%'
    * La 2ème utilise des SELECT imbriqués. Je ne sais pas comment ajouter une clause WHERE , par exemple sur la couleur..

    Qu'est ce qui sera le mieux à l'usage, sachant que je veux utiliser les 2 tables item et list pour des colonnes d'autres tables que "personne" ?

    Merci d'avance

  2. #2
    Membre à l'essai
    Inscrit en
    Novembre 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    Pour info, la première requête peut être écrite plus "joliment" ainsi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    SELECT
    u_nom, p_prenom,
    c.it_nom AS couleur,
    f.it_nom AS fruit,
    l.it_nom AS legume
    FROM personne p 
    INNER JOIN (item c NATURAL JOIN liste) AS c ON p.couleur = c.id_it
    INNER JOIN (item f NATURAL JOIN liste) AS f ON p.fruit = f.id_it
    INNER JOIN (item l NATURAL JOIN liste) AS l ON p.legume = l.id_it
     
    WHERE 
     
    c.it_nom LIKE 'bl%'

  3. #3
    Membre à l'essai
    Inscrit en
    Novembre 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    J'ai testé les coûts via un EXPLAIN :

    Requête 1 (avec les INNER JOIN et sans WHERE)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Hash Join  (cost=221.33..261.85 rows=330 width=160)
    Requête 2 (avec les SELECT imbriqués)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Seq Scan on personne p  (cost=0.00..16395.48 rows=330 width=76)
    Je ne suis pas spécialiste des coûts, mais il me semble que la 1ère est bien plus performante ?

  4. #4
    Membre émérite
    Profil pro
    Inscrit en
    Octobre 2008
    Messages
    1 874
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 874
    Points : 2 890
    Points
    2 890
    Par défaut
    A quoi servent les jointures avec la table liste? Il me semble que si elles n'étaient pas là, le résultat serait le même. Si c'est le cas autant les enlever.

  5. #5
    Membre à l'essai
    Inscrit en
    Novembre 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    Citation Envoyé par estofilo Voir le message
    A quoi servent les jointures avec la table liste? Il me semble que si elles n'étaient pas là, le résultat serait le même. Si c'est le cas autant les enlever.
    Entièrement d'accord ! Je ne sais pas pourquoi je traine la table liste, vu que les texte des items sont dans item. Cela aurait pu servir si je souhaitais avoir le nom de la liste dans une colonne. Mais ici c'est inutile

    Maintenant, voici les 2 nouvelles requêtes et les coûts associés:

    Requête 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    SELECT
    u_nom, p_prenom,
    c.it_nom AS couleur,
    f.it_nom AS fruit,
    l.it_nom AS legume
    FROM personne p 
    INNER JOIN item c ON p.couleur = c.id_it
    INNER JOIN item f ON p.fruit = f.id_it
    INNER JOIN item l ON p.legume = l.id_it
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "Hash Join  (cost=108.30..135.21 rows=330 width=160)"
    Requête 2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    SELECT
    u_nom, p_prenom,
    (SELECT it_nom FROM item WHERE id_it = p.couleur) AS mycouleur,
    (SELECT it_nom FROM item WHERE id_it = p.fruit) AS myfruit,
    (SELECT it_nom FROM item WHERE id_it = p.legume) AS mylegume
    FROM personne p
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    "Seq Scan on personne p  (cost=0.00..8198.20 rows=330 width=76)"
    Au final, quelle est la meilleure méthode ? La plus propre, celle qui permettra de réaliser des requêtes plus complexes sans difficulté ? La plus performante ?

  6. #6
    Modérateur

    Avatar de CinePhil
    Homme Profil pro
    Ingénieur d'études en informatique
    Inscrit en
    Août 2006
    Messages
    16 801
    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 801
    Points : 34 063
    Points
    34 063
    Billets dans le blog
    14
    Par défaut
    Je suppose que les colonnes couleur, fruit et legume sont indexées puisque ce sont des clés étrangères ?

    Si le cost est exprimé en secondes, 108 secondes avec seulement 330 lignes, il y a un problème quelque part !

    La première requête est meilleur sur le plan conceptuel mais je suis étonné de son résultat par rapport à la seconde.

  7. #7
    Membre à l'essai
    Inscrit en
    Novembre 2005
    Messages
    23
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 23
    Points : 16
    Points
    16
    Par défaut
    Citation Envoyé par CinePhil Voir le message
    Je suppose que les colonnes couleur, fruit et legume sont indexées puisque ce sont des clés étrangères ?
    Non, je n'avais pas indexé

    Si le cost est exprimé en secondes, 108 secondes avec seulement 330 lignes, il y a un problème quelque part !
    Non, les coûts donnés, si je me souviens bien, ne sont pas donnés en seconde.
    Je recherche dans la doc...
    https://postgresql.developpez.com/do...tion/francais/ nous dit qu'ils sont "mesurés en unités de récupération de pages sur le disque". Il y a en fait le temps de démarrage, et le temps d'exécution totale.
    Il n'y a pas non plus 330 lignes (seulement 10).

    Donc dans mon cas, même sans index, le temps d'execution total était donc en fait bien meilleur avec la requête 1 (135) qu'àvec la 2 (8198)

    La première requête est meilleur sur le plan conceptuel mais je suis étonné de son résultat par rapport à la seconde.
    Et depuis l'ajout d'index,
    Requête 1:
    "Nested Loop (cost=0.00..63.55 rows=3 width=160)"
    Requête 2:
    "Seq Scan on personne p (cost=0.00..75.44 rows=3 width=76)"

    On est donc encore gagnant avec la 1, comme quoi quand c'est mieux au niveau conceptuel, c'est souvent mieux au niveau performances.

    Merci de m'avoir obligé à réfléchir !

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

Discussions similaires

  1. Choix entre deux requêtes
    Par mromain dans le forum Développement
    Réponses: 5
    Dernier message: 15/07/2014, 21h20
  2. Choix entre requête SQL ou mapping entre tables
    Par webfranc dans le forum Connectivité
    Réponses: 4
    Dernier message: 25/01/2011, 14h52
  3. [VxiR2] Choix entre 2 requêtes avec condition de date
    Par wesaurel dans le forum Deski
    Réponses: 7
    Dernier message: 20/01/2010, 12h11
  4. Etude de performance entre 2 requêtes
    Par Pilloutou dans le forum Langage SQL
    Réponses: 7
    Dernier message: 10/10/2007, 11h01
  5. [Technique] Conflits entre plusieurs requêtes
    Par Neowile dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 24/03/2003, 09h37

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