Thank you all for your valuable input. I have tried creating a partial index, a GIST index, and a GIST + partial index, as suggested, but it does not seem to make a significant difference. For instance:

CREATE INDEX test_table_1_interval_idx ON test_table_1 USING GIST
   (box(point(start_ts::abstime::integer, start_ts::abstime::integer), 
point(end_ts::abstime::integer, end_ts::abstime::integer)))
   WHERE id = g_id;

ANALYZE test_table_1;

EXPLAIN ANALYZE SELECT count(*) FROM test_table_1
   INNER JOIN test_table_2 ON (test_table_2.s_id=13300613 AND test_table_1.id = 
test_table_2.n_id)
   WHERE box(point(start_ts::abstime::integer, start_ts::abstime::integer), 
point(end_ts::abstime::integer, end_ts::abstime::integer))
       ~ 
box(point(now()::abstime::integer,now()::abstime::integer),point(now()::abstime::integer,now()::abstime::integer))
   AND test_table_1.id = test_table_1.g_id;
QUERY PLAN -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Aggregate  (cost=15.09..15.10 rows=1 width=0) (actual time=69.771..69.772 
rows=1 loops=1)
  ->  Nested Loop  (cost=9.06..15.08 rows=1 width=0) (actual 
time=69.752..69.752 rows=0 loops=1)
        ->  Index Scan using test_table_1_interval_idx on test_table_1  
(cost=0.07..4.07 rows=1 width=22) (actual time=2.930..3.607 rows=135 loops=1)
              Index Cond: (box(point((((start_ts)::abstime)::integer)::double 
precision, (((start_ts)::abstime)::integer)::double precision), 
point((((end_ts)::abstime)::integer)::double precision, 
(((end_ts)::abstime)::integer)::double precision)) ~ 
box(point((((now())::abstime)::integer)::double precision, 
(((now())::abstime)::integer)::double precision), 
point((((now())::abstime)::integer)::double precision, 
(((now())::abstime)::integer)::double precision)))
        ->  Bitmap Heap Scan on test_table_2  (cost=8.99..11.00 rows=1 
width=12) (actual time=0.486..0.486 rows=0 loops=135)
              Recheck Cond: ((test_table_2.s_id = 13300613::numeric) AND 
("outer".id = test_table_2.n_id))
              ->  BitmapAnd  (cost=8.99..8.99 rows=1 width=0) (actual 
time=0.485..0.485 rows=0 loops=135)
                    ->  Bitmap Index Scan on test_table_2_s_id  
(cost=0.00..2.17 rows=48 width=0) (actual time=0.015..0.015 rows=1 loops=135)
                          Index Cond: (s_id = 13300613::numeric)
                    ->  Bitmap Index Scan on test_table_2_n_id  
(cost=0.00..6.57 rows=735 width=0) (actual time=0.467..0.467 rows=815 loops=135)
                          Index Cond: ("outer".id = test_table_2.n_id)
Total runtime: 69.961 ms

(Note: without the GIST index the query currently runs in about 65ms)

Its row estimates are still way off. As a matter of fact, it almost seems as if the index doesn't affect row estimates at all.

What would you guys suggest?

Thanks,

Alex

Greg Stark wrote:
You could actually take short cuts using expression indexes to do this. If it
works out well then you might want to implement a real data type to avoid the
overhead of the SQL conversion functions.

Here's an example. If I were to do this for real I would look for a better
datatype than the box datatype and I would wrap the whole conversion in an SQL
function. But this will serve to demonstrate:

stark=> create table interval_test (start_ts timestamp with time zone, end_ts 
timestamp with time zone);
CREATE TABLE

stark=> create index interval_idx on interval_test using gist 
(box(point(start_ts::abstime::integer, end_ts::abstime::integer) , 
point(start_ts::abstime::integer, end_ts::abstime::integer)));
CREATE INDEX

stark=> explain select * from interval_test where 
box(point(now()::abstime::integer,now()::abstime::integer),point(now()::abstime::integer,now()::abstime::integer))
 ~ box(point(start_ts::abstime::integer, end_ts::abstime::integer) , 
point(start_ts::abstime::integer, end_ts::abstime::integer));
QUERY PLAN -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 Index Scan using interval_idx on interval_test  (cost=0.07..8.36 rows=2 
width=16)
   Index Cond: (box(point((((now())::abstime)::integer)::double precision, 
(((now())::abstime)::integer)::double precision), 
point((((now())::abstime)::integer)::double precision, 
(((now())::abstime)::integer)::double precision)) ~ 
box(point((((start_ts)::abstime)::integer)::double precision, 
(((end_ts)::abstime)::integer)::double precision), 
point((((start_ts)::abstime)::integer)::double precision, 
(((end_ts)::abstime)::integer)::double precision)))
(2 rows)


---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster

Reply via email to