The question:
I was querying like this:
SELECT count(*)
FROM orders
WHERE planned_shipping_date >= '2022-04-04'
AND planned_shipping_date < '2022-04-05'
Then I came across this answer and, because in more complicated queries it made the query easier to read, I rewrote the query like this:
SELECT count(*)
FROM orders
WHERE planned_shipping_date <@ daterange('2022-04-04', '2022-04-05')
I believe they are semantically identical, but look at the plans:
Aggregate (cost=76.91..76.92 rows=1 width=8) (actual time=1.066..1.068 rows=1 loops=1)
-> Index Only Scan using orders_planned_shipping_date_idx on orders (cost=0.29..69.73 rows=2872 width=0) (actual time=0.067..0.646 rows=2813 loops=1)
Index Cond: ((planned_shipping_date >= '2022-04-04'::date) AND (planned_shipping_date < '2022-04-05'::date))
Heap Fetches: 0
Aggregate (cost=2753.57..2753.58 rows=1 width=8) (actual time=18.309..18.311 rows=1 loops=1)
-> Index Only Scan using orders_planned_shipping_date_idx on orders (cost=0.29..2751.93 rows=655 width=0) (actual time=17.520..18.132 rows=2813 loops=1)
Filter: (planned_shipping_date <@ '[2022-04-04,2022-04-05)'::daterange)
Rows Removed by Filter: 128138
Heap Fetches: 0
The use of the date range seems to preclude the use of an index.
Do I need a different index or should I just not use date ranges like this?
The Solutions:
Below are the methods you can try. The first solution is probably the best. Try others if the first one doesn’t work. Senior developers aren’t just copying/pasting – they read the methods carefully & apply them wisely to each case.
Method 1
Yes, your queries are semantically identical, but syntax matters too.
In order to be supported by an index, a WHERE
condition has to look like this:
<indexed expression> <operator> <constant>
-
<indexed expression>
is what was used inCREATE INDEX
-
<operator>
is an operator from the operator class of the index -
<constant>
has to be constant for the duration of the index scan (at leastSTABLE
)
Additionally, PostgreSQL knows support functions that allow it to use index scans in certain other cases, but that does not apply here.
Your problem is the operator <@
, which is not supported by B-tree indexes. As a consequence, PostgreSQL cannot use the index to check your condition. So keep using your original query.
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0