PostgreSQLでIndex-Only Scanが有効になるのは、Visibility Mapが0(ブロック中、不要なタプルが存在しない、かつどのトランザクションも更新していない)のときのみ。
あるブロックに対してINSERT、UPDATE、DELETEが行われると、VACUUMが実行されるまでIndex-Only Scanが有効にならない。
Index-Only Scanが効いているか確認する簡単な方法は、EXPLAINではなくEXPLAIN ANALYZEを実行しHeap Fetchesが0になっているかどうかを見ること。
comsdb=# explain analyze select id from test where id = 3;
QUERY PLAN
-----------------------------------------------------------------------------------------------------------
-----------
Index Only Scan using test_pkey on test (cost=0.00..3.27 rows=1 width=12) (actual time=0.042..0.043 rows=
1 loops=1)
Index Cond: (id = 3::numeric)
Heap Fetches: 0
Total runtime: 0.152 ms
(4 rows)
もし、Visibility Mapが1で実際にはタプルにアクセスしていれば、Heap Fetchesが1以上となる。
INSERTしかしていなければ、ブロック中、該当のidを持ったデータは1件なので、アクセスするタプルは1件である。
VACUUM後、(HOTが効かない場合に限るが)UPDATEを2度していれば最新のデータにたどり着くまでに3回かかり、Heap Fetches: 3
となる。