This is the "slow" plan (with inlining): Nested Loop (cost=1162.01..12106.68 rows=1 width=4) (actual time=75.084..164671.655 rows=5118 loops=1) Join Filter: (cte.id = public._test_pos.id) CTE cte -> Hash Join (cost=442.34..1162.01 rows=6667 width=4) (actual time=36.297..102.592 rows=20000 loops=1) Hash Cond: (public._test_pos.id = _test_time.id) -> Seq Scan on _test_pos (cost=0.00..428.00 rows=20000 width=4) (actual time=0.005..17.363 rows=20000 loops=1) -> Hash (cost=359.00..359.00 rows=6667 width=4) (actual time=36.274..36.274 rows=20000 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 547kB -> Seq Scan on _test_time (cost=0.00..359.00 rows=6667 width=4) (actual time=0.008..18.628 rows=20000 loops=1) Filter: ((some_time)::timestamp without time zone <= (('2012-05-15 00:00:00'::timestamp without time zone)::my_timestamp)::timestamp without time zone) -> Seq Scan on _test_pos (cost=0.00..10728.00 rows=1 width=4) (actual time=11.758..136.853 rows=5118 loops=1) Filter: ((('0101000020E61000000000000000001C400000000000001C40'::geography && _st_expand(pos, 300000::double precision)) AND (pos && '0101000020E61000000000000000001C400000000000001C40'::geography) AND _st_dwithin('0101000020E61000000000000000001C400000000000001C40'::geography, pos, 300000::double precision, true)) OR (('0101000020E61000000000000000001C400000000000001C40'::geography && _st_expand(pos, 400000::double precision)) AND (pos && '0101000020E61000000000000000001C400000000000001C40'::geography) AND _st_dwithin('0101000020E61000000000000000001C400000000000001C40'::geography, pos, 400000::double precision, true))) -> CTE Scan on cte (cost=0.00..133.34 rows=6667 width=4) (actual time=0.008..16.017 rows=20000 loops=5118) Total runtime: 164678.566 ms This is the "fast" plan (without inlining): Hash Join (cost=23401.07..39268.53 rows=3334 width=4) (actual time=158.753..271.443 rows=5118 loops=1) Hash Cond: (cte.id = public._test_pos.id) CTE cte -> Merge Join (cost=2639.22..12673.05 rows=666700 width=4) (actual time=72.092..155.530 rows=20000 loops=1) Merge Cond: (_test_time.id = public._test_pos.id) -> Sort (cost=782.45..799.12 rows=6667 width=4) (actual time=36.718..52.012 rows=20000 loops=1) Sort Key: _test_time.id Sort Method: quicksort Memory: 1294kB -> Seq Scan on _test_time (cost=0.00..359.00 rows=6667 width=4) (actual time=0.013..18.769 rows=20000 loops=1) Filter: ((some_time)::timestamp without time zone <= (('2012-05-15 00:00:00'::timestamp without time zone)::my_timestamp)::timestamp without time zone) -> Sort (cost=1856.77..1906.77 rows=20000 width=4) (actual time=35.365..50.692 rows=20000 loops=1) Sort Key: public._test_pos.id Sort Method: quicksort Memory: 1294kB -> Seq Scan on _test_pos (cost=0.00..428.00 rows=20000 width=4) (actual time=0.006..16.802 rows=20000 loops=1) -> CTE Scan on cte (cost=0.00..13334.00 rows=666700 width=4) (actual time=72.097..190.022 rows=20000 loops=1) -> Hash (cost=10728.00..10728.00 rows=1 width=4) (actual time=56.369..56.369 rows=5118 loops=1) Buckets: 1024 Batches: 1 Memory Usage: 140kB -> Seq Scan on _test_pos (cost=0.00..10728.00 rows=1 width=4) (actual time=11.355..50.909 rows=5118 loops=1) Filter: ((('0101000020E61000000000000000001C400000000000001C40'::geography && _st_expand(pos, 300000::double precision)) AND (pos && '0101000020E61000000000000000001C400000000000001C40'::geography) AND _st_dwithin('0101000020E61000000000000000001C400000000000001C40'::geography, pos, 300000::double precision, true)) OR (('0101000020E61000000000000000001C400000000000001C40'::geography && _st_expand(pos, 400000::double precision)) AND (pos && '0101000020E61000000000000000001C400000000000001C40'::geography) AND _st_dwithin('0101000020E61000000000000000001C400000000000001C40'::geography, pos, 400000::double precision, true))) Total runtime: 276.209 ms