Reply to comment
Do I need where the columns are in the same index order?
The order of expressions in the WHERE completely irrelevant ; SQL is not a procedural language.
Correct mistakes
The timestamp column should not be called a "date" for several reasons. Obviously, this is a timestamp , not a date . But more importantly, date is a reserved word in all SQL standards and a type and function name in Postgres and should not be used as an identifier.
You must provide the correct information with your question, including a full definition of the table and final information on existing indexes. It might be nice for me to start by reading the index chapter in the manual .
The WHERE conditions on the timestamp are most likely incorrect:
and date >= '2013-04-04' and date <= '2013-05-05'
The upper bound for the timestamp column should probably be excluded:
and date >= '2013-04-04' and date < '2013-05-05'
Index
If a multi- column pointer @Quassnoi is provided , your query will be much faster, since all qualification rows can be read from one continuous block of index data. No line is read in vain (and later disqualified), as is your case now.
But 500k lines will still take some time. Usually you should check visibility and retrieve additional columns from the table. checking only the index may be an option in Postgres 9.2 +.
The order of the columns is best because the rule of thumb is: columns for equality first - then for ranges. More explanation and links in this related answer to dba.SE.
You can speed up the process by arranging the table according to this index so that you need to read a minimum of blocks from the table - unless you have other requirements that oppose this!
If you want faster, however, you can arrange the physical order of the rows in the table. If you can afford to lock your table for only a few seconds (for example, after hours) to rewrite the table and arrange the rows according to the index:
ALTER TABLE foo_table CLUSTER ON idx_myindex_idx;
If concurrent use is a problem, consider pg_repack , which can do the same without blocking exclusively.
Effect: fewer blocks must be read from the table, and everything is pre-sorted. This is a one-time effect that worsens over time if you write on the table. Therefore, you repeat it from time to time.
I copied and adapted the last chapter from this related answer on dba.SE.