+1  A: 

Try something like this:

create temporary table test (d date);

insert into test select '1970-01-01'::date+generate_series(1,50*365);

analyze test

create function month_day(d date) returns int as $$
  select extract(month from $1)::int*100+extract(day from $1)::int $$
language sql immutable strict;

create index test_d_month_day_idx on test (month_day(d));

explain analyze select * from test
  where month_day(d)>=month_day('2000-04-01')
  and month_day(d)<=month_day('2000-04-05');
Tometzky
It was sluggish because the tables were not ordered properly. I fixed this by (1) Reinserting the data in order of primary key; (2) added a CLUSTER'ed index.
Dave Jarvis
+2  A: 

Your problem is that you have a where clause depending on a calculation of the date. There is no way the database can use an index if it needs to fetch every row and do a calculation on it before knowing if the date will match.

Unless you rewrite it to be in the form where the database has a fixed range to check which does not depend on the data it is to retrieve you will always have to scan the table.

Cobusve
@Cobusive: I was under the impression that GIN and GiST can avoid this. Also, I am looking for the best solution. A full table scan is not an option; there are nearly 300 million rows! :-) MySQL could execute the query in 5 seconds; PostgreSQL has yet to finish.
Dave Jarvis
A: 

I think to run this efficiently across those partitions I would have your app be alot smarter about the date ranges. Have it generate an actual list of dates to check per partition and then have it generate one query with a UNION between the partitions. It sounds like your data set is pretty static, so a CLUSTER on your date index could greatly improve performance as well.

rfusca
@rfusca: I've thought about this; I could have the application generate part of the WHERE clause, but then I'd be tightly coupling two completely different systems: the website and the report engine.
Dave Jarvis
You could move the dynamic generation of the where clause into a pl/pgsql function and then you could just have it build the query and its just a "select * from my_proc(parameters..)" - no different than before.
rfusca
@rfusca: That's an interesting proposition as well. Once I get the basic query working (and fast), I'll look into this more. Thank you!
Dave Jarvis