我有一张桌子:
create table test_coordinates(
coordinates geometry,
radius integer not null default random() * 20000 + 1000
);
这是带有半径的设定点-本质上是圆形。
我想看看给定点位于地球表面的哪个圆圈上。我想为此使用索引,所以我以另一种方式查询:
select * from test_coordinates
where st_covers(st_buffer(
coordinates::geography,
radius,
st_makepoint(59.91033806688409, 10.74357882142067));
以这种方式索引表:
create index "polygon_index" on test_coordinates
using gist(st_buffer(
coordinates::geography,
radius));
如analyze explain
所示,查询使用索引。到目前为止,一切都很好。但是,知道st_buffer
可以创建一个内切多边形,因此这会减少一些结果,因此我想通过向其添加5%的半径来稍微扩展缓冲区。现在,索引和查询将如下所示:
create index "polygon_index" on test_coordinates
using gist(st_buffer(
coordinates::geography,
radius + radius / 20));
explain analyse select * from test_coordinates
where st_covers(st_buffer(
coordinates::geography,
radius + radius / 20), -- note: don't mind that it's not precise; in reality it's followed by st_dwithin
st_makepoint(59.91033806688409, 10.74357882142067));
令人惊讶的是,现在没有使用索引。添加+ radius / 20
会以某种方式阻止其使用。为什么会这样?
解决无法在我发现的半径中添加某些东西的唯一方法是更改坐标列类型本身:
alter table test_coordinates alter column coordinates type geography;
然后,如果我从上方删除了对geography
的所有强制类型转换,则在索引和查询中同时添加+ radius / 20
不会阻止索引的使用。为什么更改列类型有效,但查询和索引中的简单强制转换却无效?这是错误吗?有没有一种方法可以在不更改列类型的情况下完成此操作?