I'm talking about this feature.
I have master table:
logstore=# \d history_log
Table "public.history_log"
Column | Type |
-----------+--------------------------+-----------------------------------------------------------
id | bigint | NOT NULL DEFAULT nextval('history_log__id_seq'::regclass)
tstamp | timestamp with time zone | NOT NULL DEFAULT now()
session | character varying(40) |
action | smallint | NOT NULL
userid | integer |
urlid | integer |
Indices:
"history_log__id_pkey" PRIMARY KEY, btree (id)
Triggers:
insert_history_log_trigger BEFORE INSERT ON history_log FOR EACH ROW EXECUTE PROCEDURE history_log_insert_trigger()
and a set of child tables partitioned by tstamp column:
logstore=# \d history_log_201304
Table "public.history_log_201304"
Column | Type |
-----------+--------------------------+-----------------------------------------------------------
id | bigint | NOT NULL DEFAULT nextval('history_log__id_seq'::regclass)
tstamp | timestamp with time zone | NOT NULL DEFAULT now()
session | character varying(40) |
action | smallint | NOT NULL
userid | integer |
urlid | integer |
Indices:
"history_log_201304_pkey" PRIMARY KEY, btree (id)
"history_log_201304_tstamp" btree (tstamp)
"history_log_201304_userid" btree (userid)
Constraints:
"history_log_201304_tstamp_check" CHECK (tstamp >= '2013-04-01 00:00:00+04'::timestamp with time zone AND tstamp < '2013-05-01 00:00:00+04'::timestamp with time zone)
Inherits: history_log
So what is my problem - when I do queries that have WHERE condition constrained by tstamp directly on child tables - it works very fast.
logstore=# EXPLAIN SELECT userid FROM history_log_201304 WHERE tstamp >= (current_date - interval '3 days')::date::timestamptz AND tstamp < current_date::timestamptz AND action = 13;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------
Index Scan using history_log_201304_tstamp on history_log_201304 (cost=0.01..8.37 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
But when I try to do the same on master table - it goes to Seq Scan:
logstore=# EXPLAIN SELECT userid FROM history_log WHERE tstamp >= (current_date - interval '3 days')::date::timestamptz AND tstamp < current_date::timestamptz AND action = 13;
QUERY PLAN
------------------------------------------------------------------------------------------------------------------------------------
---------------
Result (cost=0.00..253099.82 rows=1353838 width=4)
-> Append (cost=0.00..253099.82 rows=1353838 width=4)
-> Seq Scan on history_log (cost=0.00..0.00 rows=1 width=4)
Filter: ((action = 13) AND (tstamp < ('now'::cstring)::date) AND (tstamp >= ((('now'::cstring)::date - '3 days'::inte
rval))::date))
-> Index Scan using history_log_201203_tstamp on history_log_201203 history_log (cost=0.01..9.67 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201204_tstamp on history_log_201204 history_log (cost=0.01..9.85 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201205_tstamp on history_log_201205 history_log (cost=0.01..10.39 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201206_tstamp on history_log_201206 history_log (cost=0.01..10.32 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201207_tstamp on history_log_201207 history_log (cost=0.01..10.09 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201208_tstamp on history_log_201208 history_log (cost=0.01..10.35 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201209_tstamp on history_log_201209 history_log (cost=0.01..10.53 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201210_tstamp on history_log_201210 history_log (cost=0.01..11.83 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201211_tstamp on history_log_201211 history_log (cost=0.01..11.87 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201212_tstamp on history_log_201212 history_log (cost=0.01..12.40 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201301_tstamp on history_log_201301 history_log (cost=0.01..12.35 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201302_tstamp on history_log_201302 history_log (cost=0.01..12.35 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201303_tstamp on history_log_201303 history_log (cost=0.01..252959.45 rows=1353824 width=
4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
-> Index Scan using history_log_201304_tstamp on history_log_201304 history_log (cost=0.01..8.37 rows=1 width=4)
Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date))
Filter: (action = 13)
What's happening here? Why queries to master table isn't just as fast?
I have constraint_exclusion set to on.
Edit: I found solution by accident and writing it here for the sake of readability.
Till today I had wrong constraints - my tstamp column is of timestamp WITH time zone type, constraints were build on timestamp WITHOUT time zone. I fixed that, fixed my queries to have type casts - but still queries to master table took minutes instead of seconds. That was my last option so I went to SO. During conversation I went to DB and issued EXPLAIN ANALYZE to all child tables to get some actual numbers - and after that queries on master table became fast!