微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

postgresql – ST_DWithin不使用带非文字参数的索引

我在Amazon RDS上使用Postresql 9.3 w / PostGIS 2.1.8.我有一个名为project_location的表,它定义了“geo-fences”(每个都基本上是一个坐标和半径).使用名为“location”的几何列和名为“radius”的双列存储地理围栏.我在location列上有一个空间索引.
CREATE TABLE project_location
(
  ...
  location geography(Point,4326),radius double precision NOT NULL,...
)
CREATE INDEX gix_project_location_location 
ON project_location USING gist (location);

该表目前有大约50,000条记录.如果我查询表以查找geo-fence包含一个点的所有project_locations,就像

SELECT COUNT(*) 
FROM project_location 
WHERE ST_DWithin(location,ST_SetSRID(ST_MakePoint(-84.1000,34.0000),4326)::geography,radius);

我发现没有使用空间索引. EXPLAIN的结果显示如下:

"Aggregate  (cost=11651.97..11651.98 rows=1 width=0)"
"  ->  Seq Scan on project_location  (cost=0.00..11651.97 rows=1 width=0)"
"        Filter: ((location && _st_expand('0101000020E610000066666666660655C00000000000004140'::geography,radius)) AND ('0101000020E610000066666666660655C00000000000004140'::geography && _st_expand(location,radius)) AND _st_dwithin(location,'0101000020E610000066666666660655C00000000000004140'::geography,radius,true))"

但是,如果半径是一个常数值,如下所示

SELECT COUNT(*) 
FROM project_location 
WHERE ST_DWithin(location,1000);

空间索引用于EXPLAIN显示

"Aggregate  (cost=8.55..8.56 rows=1 width=0)"
"  ->  Index Scan using gix_project_location_location on project_location  (cost=0.28..8.55 rows=1 width=0)"
"        Index Cond: (location && '0101000020E610000066666666660655C00000000000004140'::geography)"
"        Filter: (('0101000020E610000066666666660655C00000000000004140'::geography && _st_expand(location,1000::double precision)) AND _st_dwithin(location,1000::double precision,true))"

在阅读了ST_DWithin如何使用索引后,我理解为什么会这样.基本上,基于半径的边界框用于“预过滤”候选点以在对这些点进行相对昂贵的距离计算之前确定可能的匹配.

我的问题是有没有办法进行这种类型的搜索,以便可以使用空间索引?基本上是一种用一堆可变半径地理围栏来查询表方法吗?

PostGIS允许使用功能索引加快查询速度.我不确定如何在地理数据类型中执行此操作,因为那里没有ST_Expand,但如果将数据存储在某些Mercator投影中(例如,SRID = 3857),查询将非常简单.

理念:

>生成一个由您的点周围的半径单位扩展的框;
>在这些盒子上建立一个索引;
>根据这些框查询用户点;
>按精确半径重新检查.

在project_location表上:

create index on project_location using gist (ST_Expand(location,radius));

现在,您可以使用ST_Expand(位置,半径),就好像它是您的索引几何列一样.

select count(*) from project_location where ST_Intersects(ST_Expand(location,radius),<your_point>) and ST_distance(location,<your_point>) < radius;

现在您正在跳过ST_DWithin,因为您希望重新检查从不尝试使用索引,并在几何函数上使用索引.

对于地理位置,您可以尝试使用ST_Envelope(ST_Buffer(geom,radius))将ST_Expand存根.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐