PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 15/10/2010 01:03:58

cbernard
Membre

Plans d'exécution différents sur même requête

Bonjour,

Je fais face à un problème très étrange.

En regardant le plan d'exécution d'une requête, celui-ci diffère selon les valeurs que je passe au WHERE.

La requête :
explain  analyze
select
    session_id
from
    session
where
    id = XXXX and
    session_id between 300100000 and 303204368

Lorsqu'id = 9214 :
QUERY PLAN
Index Scan using session_id_idx on session  (cost=0.00..91050.10 rows=5848 width=4) (actual time=0.797..324.467 rows=207 loops=1)
  Index Cond: ((session_id >= 300100000) AND (session_id <= 303204368) AND (id = 9214))
Total runtime: 324.532 ms

Lorsqu'id = 8131 :
QUERY PLAN
Bitmap Heap Scan on session  (cost=60380.26..62442.27 rows=517 width=4) (actual time=60816.526..60816.558 rows=4 loops=1)
  Recheck Cond: ((id = 8131) AND (session_id >= 300100000) AND (session_id <= 303204368))
  ->  BitmapAnd  (cost=60380.26..60380.26 rows=517 width=0) (actual time=60816.392..60816.392 rows=0 loops=1)
        ->  Bitmap Index Scan id_idx  (cost=0.00..1015.53 rows=53243 width=0) (actual time=0.128..0.128 rows=325 loops=1)
              Index Cond: (id = 8131)
        ->  Bitmap Index Scan on pk_t_session_sin  (cost=0.00..59364.22 rows=2829602 width=0) (actual time=60814.642..60814.642 rows=3103959 loops=1)
              Index Cond: ((session_id >= 300100000) AND (session_id <= 303204368))
Total runtime: 60816.602 ms

Je précise qu'il existe un indexe sur id et sur (session_id,id).

Je ne comprend donc pas pourquoi les plans d'exécution sont différents.

Merci d'avance pour vos réponses,
Christophe

Dernière modification par cbernard (15/10/2010 09:17:06)

Hors ligne

#2 15/10/2010 07:49:03

Marc Cousin
Membre

Re : Plans d'exécution différents sur même requête

Bonjour,

C'est «normal». Il prend en compte le nombre d'enregistrements ramenés par les différents éléments de la clause where, afin d'essayer de déterminer le meilleur plan d'exécution. Suivant les valeurs d'id, il estime différemment le nombre d'enregistrements ramenés par la requête, et choisit un plan différent.

Le vrai problème, c'est que votre index n'est pas 'dans le bon sens' pour la requête: il devrait être sur (id, session_id), puisque vous demandez une valeur précise d'id et une plage de valeurs pour session_id (c'est du à la structure des index btree composés sur plusieurs colonnes).

Autre problème: je ne comprends pas pourquoi il faut 60 secondes à la base pour parcourir pk_t_session_sin. L'index doit être très fragmenté, et devrait probablement être reconstruit (REINDEX). À moins que votre machine ne soit réellement très lente (disques durs lents), et que la première requête ait bénéficié du cache, et pas la seconde.


Marc.

Hors ligne

#3 15/10/2010 09:41:03

cbernard
Membre

Re : Plans d'exécution différents sur même requête

Bonjour,

Et merci pour les explications, notamment sur le "sens" de l'index, je n'avais pas saisi que l'ordre avait un impact sur le plan d'exécution.
Je vais donc recréer un nouvel index et par la même occasion reindexer pk_t_session car les disques sont rapides (SAS 15k)

Je referai une analyse par la suite.

Christophe

Hors ligne

#4 15/10/2010 10:34:19

gleu
Administrateur

Re : Plans d'exécution différents sur même requête

Vous pouvez aussi jouer avec le paramètre random_page_cost (en l'abaissant) pour favoriser l'utilisation des index.


Guillaume.

Hors ligne

#5 15/10/2010 10:55:40

cbernard
Membre

Re : Plans d'exécution différents sur même requête

Merci pour le commentaire, j'avais effectivement changé random_page_cost à 2.0 et noté un gain d'environ 20% sur l'EXPLAIN.

Christophe

Hors ligne

Pied de page des forums