Problème de performances sur une jointure

From: Jonathan Ballet <jon(at)multani(dot)info>
To: pgsql-fr-generale <pgsql-fr-generale(at)postgresql(dot)org>
Subject: Problème de performances sur une jointure
Date: 2006-04-14 15:40:03
Message-ID: 443FC253.9080406@multani.info
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-fr-generale

Bonjour,

j'ai une application qui utilise une base de données PostgreSQL (version 7.4), et sous fortes
charges, j'ai des requêtes qui prennent pas mal de temps. Il est donc l'heure d'optimiser tout ça :)

J'ai donc deux tables qu'on va appeler A et B. Voilà grosso-modo comment elles se présentes :

- A : contient un peu plus de 8000 enregistrements, et est composée d'une dizaine de colonne, la
plupart étant des clés étrangères vers des identifiants d'autres tables de la base de données

- B : contient un peu plus de 400000 enregistrements. Table de la forme sous la forme cle/valeur,
avec une clé étrangère sur l'identifiant de la table A

J'ai donc des indexes sur toutes mes clés (primaires et étrangères), et le problème survient, quand
j'essaie de faire une requête de ce genre :

SELECT A.*, B.cle, B.valeur
FROM A
LEFT OUTER JOIN B ON B.A_idA = A.idA
WHERE
A.idA IN (
[subselect]
)
ORDER BY A.idA, B.cle;

J'ai fais un EXPLAIN pour voir le plan d'exécution prévu par l'analyseur, et en fait, ce qui prends
le plus de temps correspond au tri de la clé étrangère de B vers A (B.A_idA), juste avant de faire
le OUTER JOIN :

QUERY PLAN
Sort (cost=85920.84..85930.72 rows=3952 width=139)
Sort Key: A.idA, B.cle
-> Merge IN Join (cost=78081.87..85684.74 rows=3952 width=139)
Merge Cond: (""outer"".idA = ""inner"".A_idA)
-> Merge Left Join (cost=77865.81..84393.16 rows=406795 width=139)
Merge Cond: (""outer"".idA = ""inner"".A_idA)
-> Index Scan using A_index_idA on A (cost=0.00..411.52 rows=5559 width=105)
-> Sort (cost=77865.81..78882.80 rows=406794 width=42)
Sort Key: B.A_idA
-> Seq Scan on B (cost=0.00..10194.94 rows=406794 width=42)
-> Sort (cost=216.06..216.20 rows=54 width=16)
[subselect]

A tout hasard, j'ai passé enable_seqscan à 'off' : le "cost" affiché par EXPLAIN augmente bien, le
EXPLAIN affiche bien l'utilisation de l'index scan (cf dessous), par contre, le temps d'exécution
réel de la requête n'a rien voir (quelques millisecondes au lieu de quelques dizaines de secondes) :

Sort (cost=1332190.09..1332199.97 rows=3952 width=139)
Sort Key: A.idA, B.cle
-> Merge IN Join (cost=346.07..1331953.99 rows=3952 width=139)
Merge Cond: (""outer"".idA = ""inner"".A_idA)
-> Merge Left Join (cost=0.00..1330662.60 rows=406795 width=139)
Merge Cond: (""outer"".idA = ""inner"".A_idA)
-> Index Scan using A_index_idA on A (cost=0.00..411.52 rows=5559 width=105)
-> Index Scan using B_A_idA_fkindex1 on B (cost=0.00..1325148.98 rows=406794 width=42)

En regardant les couts affichés par Explain, on voit bien que l'analyseur de Postgres choisi le
meilleur rapport, mais au final, ya un problème quand même ...

J'ai mesuré mes requêtes avec un script Python (utilisant psycopg), le résultat des requêtes n'étant
pas utilisé (pour éviter des problèmes de mesure qui prennent en compte le temps d'affichage des
résultats). J'ai bien pris soin d'effectuer des "VACUUM ANALYSE" sur A et B à chaque fois que
j'essayais de nouveaux indexes.

Là du coup, je flotte un peu ...

Toute aide ou explication serait la bienvenue :)

Cordialement,
Jonathan Ballet

Browse pgsql-fr-generale by date

  From Date Subject
Next Message DANTE ALEXANDRA 2006-04-19 09:39:47 Tests de regression sous Windows
Previous Message DANTE ALEXANDRA 2006-04-13 09:00:53 Re: Compilation de PostGreSQL sous Windows 64