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 :

Index d'une clé primaire composée et sous requête corrélée


Sujet :

Requêtes PostgreSQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de ymoreau
    Homme Profil pro
    Ingénieur étude et développement
    Inscrit en
    Septembre 2005
    Messages
    1 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur étude et développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 154
    Par défaut Index d'une clé primaire composée et sous requête corrélée
    Bonjour,
    J'ai deux tables (en gras les PK) :
    inverted_index: id_token, id_doc, positions (643 649 788 lignes)
    tokens: id_token, token (12 310 981 lignes)

    Je me demande de quelle manière est indexée une clé primaire composée de deux champs ? J'utilise ces deux champs dans une requête et mais les performances sont très mauvaises.

    Voici la requête et l'explain analyze sur cette requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select * from tokens where not exists (select * from inverted_index as i where i.id_token = tokens.id_token and i.id_doc != $1)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
                                                                        QUERY PLAN
    ---------------------------------------------------------------------------------------------------------------------------------------------------
     Hash Anti Join  (cost=24313919.19..27316902.92 rows=12324415 width=15) (actual time=36183259.188..154041487.640 rows=7 loops=1)
       Hash Cond: (tokens.id_token = i.id_token)
       ->  Seq Scan on tokens  (cost=0.00..202202.34 rows=12345034 width=15) (actual time=0.034..7072.352 rows=12310981 loops=1)
       ->  Hash  (cost=13754336.40..13754336.40 rows=643631663 width=4) (actual time=5775623.425..5775623.425 rows=643649781 loops=1)
             ->  Seq Scan on inverted_index i  (cost=0.00..13754336.40 rows=643631663 width=4) (actual time=0.027..3650670.164 rows=643649781 loops=1)
                   Filter: (id_doc <> $1)
     Total runtime: 154042117.430 ms
    Je ne suis pas bien sûr de ce que dit le plan, mais il me semble qu'il y a un scan complet de la table inverted_index au sein de la boucle. J'aurais naturellement pensé que la requête prendrait un sous ensemble de cette table (lorsque l'id_token est le même) pour comparer id_doc, et que l'index sur inverted_index.id_token serait utilisé pour créer ce sous ensemble.

  2. #2
    Membre Expert
    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
    Par défaut
    Il y a un scan complet de la table inverted_index, mais sauf incompréhension de ma part il ne se produit qu'une fois pour construire la table de hash temporaire.
    L'exécution cherche tous les id_token tels que id_doc<>$1, ce qui veut dire certainement presque toute la table dans le cas d'un index documentaire inversé. Il doit stocker le résultat temporairement sur disque, ce qui contribue sans doute pas mal au temps faramineux pris par la requête.

    Mais quels sont les index sur cette table?

  3. #3
    Membre éprouvé
    Avatar de ymoreau
    Homme Profil pro
    Ingénieur étude et développement
    Inscrit en
    Septembre 2005
    Messages
    1 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur étude et développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 154
    Par défaut
    En effet la condition sur id_doc fait ressortir la quasi totalité de la table, mais restreinte sur un certain id_token ça fait beaucoup moins (en moyenne théorique 643 millions divisés par 12 millions, en pratique encore moins). Il y a seulement les index des clés primaire, d'où mon interrogation sur ce qui est implicitement fait avec la clé primaire composée.

  4. #4
    Membre Expert
    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
    Par défaut
    L'index sur (id_token, id_doc) n'est pas utilisé par cette requête.
    S'il y avait peu d'entrées dans la table token, il serait intéressant pour l'optimiseur de la mettre en tête de boucle, c.a.d pour chaque token.id_token, chercher les inverted_index.id_token correspondant avec la condition additionnelle sur id_doc.
    Cette opération serait unitairement rapide grâce à l'index, mais le problème est qu'il faudrait la répéter 12 millions de fois, donc il est vraisemblable qu'au final ça serait plus lent que le plan actuel.

  5. #5
    Membre éprouvé
    Avatar de ymoreau
    Homme Profil pro
    Ingénieur étude et développement
    Inscrit en
    Septembre 2005
    Messages
    1 154
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur étude et développement
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 1 154
    Par défaut
    Merci pour les explications. Le problème c'est qu'en réalité il n'y aura pas autant de tours de boucle, ça irait de quelques dizaines à quelques milliers en gros, mais jamais 12 millions. Sur cet exemple (pas très représentatif mais quand même), on ne récupère que 7 tokens, donc utiliser l'index devrait faire gagner beaucoup de temps, et même éviter de hacher la totalité de inverted_index pour n'en utiliser qu'une faible partie au final. Est-ce qu'il y a un moyen d'indiquer ces directions dans le plan de la requête ?

  6. #6
    Membre Expert
    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
    Par défaut
    Je ne vois pas le raisonnement qui conduit à dire que quelques milliers de tours de boucle seraient suffisants. Imaginons qu'on soit en procédural, au départ on dispose du numéro de document. Quelle serait la boucle principale en question?

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

Discussions similaires

  1. Réponses: 6
    Dernier message: 01/05/2008, 12h29
  2. Réponses: 3
    Dernier message: 18/04/2008, 14h28
  3. Réponses: 4
    Dernier message: 04/01/2008, 22h34
  4. Réponses: 3
    Dernier message: 06/03/2007, 14h15
  5. [Oracle] modification d'une clé primaire composée
    Par petburn dans le forum Langage SQL
    Réponses: 3
    Dernier message: 16/03/2006, 15h58

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