You need an index on test1_id in table test2, that will change things.
Seq Scan on test1 t1 (cost=0.00..301450.63 rows=8761 width=12) (actual time=0.108..229.859 rows=8761 loops=1) SubPlan 1 -> Aggregate (cost=11.45..11.46 rows=1 width=4) (actual time=0.008..0.008 rows=1 loops=8761) -> Bitmap Heap Scan on test2 t2 (cost=3.27..11.45 rows=1 width=4) (actual time=0.007..0.007 rows=0 loops=8761) Recheck Cond: (test1_id = t1.id) Filter: ((category)::text = 'A'::text) -> Bitmap Index Scan on idx_id (cost=0.00..3.27 rows=3 width=0) (actual time=0.003..0.003 rows=3 loops=8761) Index Cond: (test1_id = t1.id) SubPlan 2 -> Aggregate (cost=11.45..11.46 rows=1 width=4) (actual time=0.007..0.008 rows=1 loops=8761) -> Bitmap Heap Scan on test2 t2 (cost=3.27..11.45 rows=1 width=4) (actual time=0.006..0.006 rows=0 loops=8761) Recheck Cond: (test1_id = t1.id) Filter: ((category)::text = 'B'::text) -> Bitmap Index Scan on idx_id (cost=0.00..3.27 rows=3 width=0) (actual time=0.003..0.003 rows=3 loops=8761) Index Cond: (test1_id = t1.id) SubPlan 3 -> Aggregate (cost=11.46..11.47 rows=1 width=8) (actual time=0.008..0.008 rows=1 loops=8761) -> Bitmap Heap Scan on test2 t2 (cost=3.27..11.45 rows=1 width=8) (actual time=0.006..0.006 rows=0 loops=8761) Recheck Cond: (test1_id = t1.id) Filter: ((category)::text = 'C'::text) -> Bitmap Index Scan on idx_id (cost=0.00..3.27 rows=3 width=0) (actual time=0.003..0.003 rows=3 loops=8761) Index Cond: (test1_id = t1.id)Total runtime: 232.419 ms