I have a table with three columns: two can be used to filter the table, and the last can be used to sort it:
create table thing(
id serial primary key,
location geometry(Point, 4326) not null,
created_at timestamptz not null default (now() at time zone 'utc'),
priority float not null
);
I have been playing with the indexes to support the following query:
select id
from thing
where st_dwithin(location, 'SRID=4326;Point($0 $1)'::geometry, $2)
and created_at >= now() - interval '$3 days'
order by priority
offset $4
limit $5;
Ideally this query could combine indexes on location, created_at, and priority to get optimal performance. Typically I'd imagine an index using btree (priority, location, created_at)
would support such a query quite well, utilizing the index during the filter and delivering results pre-sorted. However, the st_dwithin part of the filter goes unassisted by the filter since that is not a gist
index.
If I make an index using gist (priority, location, created_at)
then the query plan utilizes the index during filtering but does not deliver results pre-sorted and sorts the results unassisted by the index.
At this point I thought we'd have to split up the index, but using gist(location, created_at)
and using btree(priority)
if $5 <= 20
the query plan uses the btree index and if $5 > 20
the query plan uses the gist index.
Does anyone have any idea why this might be, and what I could do to optimize the performance of both the filtering and the sorting?
st_x
andst_y
of the point in the btree index instead, but this is obviously full of limitations and only works because location is ageometry(Point)
.