表达索引的奇怪行为

时间:2019-10-08 11:35:58

标签: postgresql postgis

我有一张桌子:

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不会阻止索引的使用。为什么更改列类型有效,但查询和索引中的简单强制转换却无效?这是错误吗?有没有一种方法可以在不更改列类型的情况下完成此操作?

0 个答案:

没有答案