我在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] 举报,一经查实,本站将立刻删除。