4

I have a table with two date like dateTo and dateFrom, i would like use daterange approach in queries and a gist index, but it seem doesn't work. The table looks like:

CREATE TABLE test (
  id         bigeserial,
  begin_date date,
  end_date   date
);
CREATE INDEX "idx1"
  ON test
  USING gist (daterange(begin_date, end_date));

Then when i try to explain a query like:

SELECT t.*
FROM test t
WHERE daterange(t.begin_date,t.end_date,'[]') && daterange('2015-12-30 00:00:00.0','2016-10-28 00:00:00.0','[]')

i get a Seq Scan.

Is this usage of gist index wrong, or is this scenario not feasible?

7
  • Why not a B-tree multicolumn index on begin_date and end_date? I think that you might get a seq scan if you have few rows. Maybe you need enough data to stress test your implementation. Commented Apr 18, 2017 at 15:53
  • 5
    You are trying to use an expression index with the wrong expression. You have daterange(begin_date, end_date) in the index, but you query your table with daterange(begin_date, end_date, '[]') (note the third parameter). Commented Apr 18, 2017 at 15:56
  • @andrei-macarie i'm using gist index because b-tree does not support range operators. Commented Apr 18, 2017 at 16:09
  • 1
    @pozs that's not true. the index will work with both. Commented Apr 18, 2017 at 16:46
  • 1
    You need to provide the explain analyze with the seqscan, and also set enable_seqscan = 0; and the same explain analyze. Commented Apr 18, 2017 at 16:54

1 Answer 1

4

You have an index on the expression daterange(begin_date, end_date), but you query your table with daterange(begin_date, end_date, '[]') && .... PostgreSQL won't do math instead of you. To re-phrase your problem, it is like you're indexing (int_col + 2) and querying WHERE int_col + 1 > 2. Because the two expressions are different, the index will not be used in any circumstances. But as you can see, you can do the math (i.e. re-phrase the formula) sometimes.

You'll either need:

CREATE INDEX idx1 ON test USING gist (daterange(begin_date, end_date, '[]'));

Or:

CREATE INDEX idx2 ON test USING gist (daterange(begin_date, end_date + 1));

Note: both of them creates a range which includes end_date. The latter one uses the fact that daterange is discrete.

And use the following predicates for each of the indexes above:

WHERE daterange(begin_date, end_date, '[]') && daterange(?, ?, ?)

Or:

WHERE daterange(begin_date, end_date + 1) && daterange(?, ?, ?)

Note: the third parameter of the range constructor on the right side of && does not matter (in the context of index usage).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.