I'm trying to optimize some of my selects using the explain analyze, and I can't understand why postgresql uses a sequentials scan instead of index scan:
explain analyze SELECT SUM(a.deure)-SUM(a.haver) as Value FROM assentaments a
LEFT JOIN comptes c ON a.compte_id = c.id WHERE c.empresa_id=2 AND c.nivell=11 AND
(a.data >='2007-01-01' AND a.data <='2007-01-31') AND c.codi_compte LIKE '6%';
------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate (cost=44250.26..44250.27 rows=1 width=12)
(actual time=334.054..334.054 rows=1 loops=1)
-> Nested Loop (cost=0.00..44249.20 rows=211 width=12)
(actual time=65.277..333.179 rows=713 loops=1)
-> Seq Scan on comptes c (cost=0.00..8001.72 rows=118 width=4)
(actual time=0.053..64.287 rows=236 loops=1)
Filter: (((codi_compte)::text ~~ '6%'::text) AND
(empresa_id = 2) AND (nivell = 11))
-> Index Scan using index_compte_id on assentaments a
(cost=0.00..307.16 rows=2 width=16) (actual time=0.457..1.138 rows=3 loops=236)
Index Cond: (a.compte_id = c.id)
Filter: ((a.data >= '2007-01-01'::date) AND (a.data <= '2007-01-31'::date))
Total runtime: 334.104 ms
(8 rows)
I've created a custom index:
CREATE INDEX "index_multiple" ON "public"."comptes" USING btree(codi_compte ASC NULLS LAST,
empresa_id ASC NULLS LAST, nivell ASC NULLS LAST);
And also I've created three new index for this three fields on comptes table just to check If it takes an index scan, but not, the result is the same:
CREATE INDEX "index_codi_compte" ON "public"."comptes" USING btree(codi_compte ASC NULLS LAST);
CREATE INDEX "index_comptes" ON "public"."comptes" USING btree(codi_compte ASC NULLS LAST);
CREATE INDEX "index_multiple" ON "public"."comptes" USING btree(codi_compte ASC NULLS LAST, empresa_id ASC NULLS LAST, nivell ASC NULLS LAST);
CREATE INDEX "index_nivell" ON "public"."comptes" USING btree(nivell ASC NULLS LAST);
thanks!
m.
EDIT:
assentaments.id and assentaments.data have their index also
select count(*) FROM comptes => 148498
select count(*) from assentaments => 2128771
select count(distinct(codi_compte)) FROM comptes => 137008
select count(distinct(codi_compte)) FROM comptes WHERE codi_compte LIKE '6%' => 368
select count(distinct(codi_compte)) FROM comptes WHERE codi_compte LIKE '6%' AND empresa_id=2; => 303
assentaments.idor onassentaments.compte_id?set enable_seqscan to off? Is it faster or slower?comptes.codi_compte?