Vous n'êtes pas identifié(e).
J'ai décelé un problème sur une de nos bases postgresql (8.2.4)
La table documents est partitionnée par identifiant de sources :
- On a parfois plusieurs sources par tables filles.
- La dernière table fille a une contrainte du type : "le doc n'est pas la source x" (table par défaut pour les nouvelles sources).
- Quelques indexes sont différents, à cause de la nature de certaines sources, mais ça ne devrait pas influer sur les tables filles à interroger.
# SHOW constraint_exclusion ;
constraint_exclusion | on
Lorsqu'on test directement avec l'identifiant de la source aucun problème, il interroge directement la bonne table fille.
#explain analyse SELECT id_source,count(*) from documents where documents.id_source in (577) and dav='today' group by id_source order by id_source;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=7428.65..7430.19 rows=77 width=2) (actual time=29.903..29.904 rows=1 loops=1)
-> Sort (cost=7428.65..7428.84 rows=77 width=2) (actual time=29.695..29.785 rows=152 loops=1)
Sort Key: public.documents.id_source
-> Append (cost=0.00..7426.23 rows=77 width=2) (actual time=4.462..29.500 rows=152 loops=1)
-> Seq Scan on documents (cost=0.00..19.60 rows=1 width=2) (actual time=0.002..0.002 rows=0 loops=1)
Filter: ((id_source = 577) AND (dav = '2010-04-22'::date))
-> Index Scan using idx_documents_z_dav on documents_z documents (cost=0.00..7406.63 rows=76 width=2) (actual time=4.458..29.345 rows=152 loops=1)
Index Cond: (dav = '2010-04-22'::date)
Filter: (id_source = 577)
Total runtime: 30.021 ms
Par contre si j'utilise une requête avec une jointure pg interroge toute les tables filles.
(il se comporte exactement de la même façon avec constraint_exclusion a 'off')
# explain analyse select name,count(*) from documents,sources where documents.id_source=sources.id and sources.name in ('toto') and dav='today' group by name order by name;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
GroupAggregate (cost=0.00..31667.07 rows=1 width=7) (actual time=117.708..117.708 rows=1 loops=1)
-> Nested Loop (cost=0.00..31666.79 rows=54 width=7) (actual time=78.417..117.312 rows=582 loops=1)
Join Filter: (public.documents.id_source = sources.id)
-> Index Scan using idx_sources_name on sources (cost=0.00..8.27 rows=1 width=11) (actual time=0.112..0.115 rows=1 loops=1)
Index Cond: (name = 'toto'::text)
-> Append (cost=0.00..31157.13 rows=40111 width=2) (actual time=0.321..94.204 rows=39178 loops=1)
-> Seq Scan on documents (cost=0.00..18.00 rows=3 width=2) (actual time=0.001..0.001 rows=0 loops=1)
Filter: (dav = '2010-04-22'::date)
-> Index Scan using idx_documents_a_id_source_dav on documents_a documents (cost=0.00..3665.17 rows=2063 width=2) (actual time=0.085..0.085 rows=0 loops=1)
Index Cond: ((public.documents.id_source = sources.id) AND (public.documents.dav = '2010-04-22'::date))
-> Index Scan using idx_documents_b_id_source_dav on documents_b documents (cost=0.00..4290.27 rows=2417 width=2) (actual time=0.051..0.051 rows=0 loops=1)
Index Cond: ((public.documents.id_source = sources.id) AND (public.documents.dav = '2010-04-22'::date))
....
-> Bitmap Heap Scan on documents_z documents (cost=2205.26..2257.24 rows=13 width=2) (actual time=5.899..5.899 rows=0 loops=1)
Recheck Cond: ((public.documents.dav = '2010-04-22'::date) AND (public.documents.id_source = sources.id))
-> BitmapAnd (cost=2205.26..2205.26 rows=13 width=0) (actual time=5.895..5.895 rows=0 loops=1)
-> Bitmap Index Scan on idx_documents_z_dav (cost=0.00..197.71 rows=8490 width=0) (actual time=5.582..5.582 rows=26675 loops=1)
Index Cond: (dav = '2010-04-22'::date)
-> Bitmap Index Scan on idx_documents_z_id_source_nod (cost=0.00..2005.17 rows=60124 width=0) (actual time=0.059..0.059 rows=0 loops=1)
Index Cond: (public.documents.id_source = sources.id)
Total runtime: 117.993 ms
Visiblement des qu'il y a une jointure avec la table source pgsql decide de shunter les contraintes.
Il se comporte de la même manière en utilisant une sous-requête.
En production, on passe d'un cout de 968000 à 11000.
Hors ligne
PostgreSQL ne peut faire d'exclusion de contrainte qui si dans la clause WHERE vous avez des contraintes qui lui permettent AU MOMENT DE LA PLANIFICATION de la requête d'éliminer des partitions.
«where documents.id_source=sources.id and sources.name in ('toto') and dav='today' group by name order by name» ne permet pas d'exclure des partitions de documents au moment de la planification : on ne sait pas à ce moment là quels ids la jointure avec sources va ramener.
Marc.
Hors ligne
Voila qui explique tout, je pensais naïvement que Pg vérifiait les contraintes "à la volée".
(enfin du coup ça m'arrange pas )
Merci.
Hors ligne