I am working on this simple example:
=> create table t1 ( a int, b int, c int );
CREATE TABLE
=> insert into t1 select a, a, a from generate_series(1,100) a;
INSERT 0 100
=> create index i1 on t1(b);
CREATE INDEX
=> vacuum t1;
VACUUM
=> explain analyze select b from t1 where b = 10;
QUERY PLAN
--------------------------------------------------------------------------------------------
Seq Scan on t1 (cost=0.00..2.25 rows=1 width=4) (actual time=0.016..0.035 rows=1 loops=1)
Filter: (b = 10)
Rows Removed by Filter: 99
Planning Time: 0.082 ms
Execution Time: 0.051 ms
(5 rows)
You can see that I select b and query on b only. And also vacuum t1; manually to make sure the Visibility information is stored in the index.
But why does Postgresql still do Seq Scan instead of index-only-scan?
Edited
After adding more rows, it will do index-only-scan:
=> insert into t1 select a, a, a from generate_series(1,2000) a;
=> vacuum t1;
=> explain analyze select b from t1 where b = 10;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------
Index Only Scan using i1 on t1 (cost=0.28..4.45 rows=10 width=4) (actual time=0.038..0.039 rows=1 loops=1)
Index Cond: (b = 10)
Heap Fetches: 0
Planning Time: 0.186 ms
Execution Time: 0.058 ms
(5 rows)
It seems like PostgreSQL doesn't like index-only-scan when the rows number is small.
explain (analyze, buffers)to see more details on the blocks (=buffers) needed by the query