【发布时间】:2017-04-16 14:32:44
【问题描述】:
我在 Amazon RDS 上使用带有 PostGIS 2.1.8 的 PostreSQL 9.3。我有一个名为 project_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 条记录。如果我查询该表以查找地理围栏包含一个点的所有 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, ST_SetSRID(ST_MakePoint(-84.1000, 34.0000),4326)::geography, 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, '0101000020E610000066666666660655C00000000000004140'::geography, 1000::double precision, true))"
阅读了 ST_DWithin 如何使用索引后,我明白为什么会这样。本质上,基于半径的边界框用于“预过滤”候选点以确定可能的匹配,然后再对这些点进行相对昂贵的距离计算。
我的问题是有什么方法可以进行这种类型的搜索以便可以使用空间索引?基本上是一种用一堆可变半径地理围栏查询表的方法?
【问题讨论】:
-
您应该标记并要求将其移至 dba.se。
-
@EvanCarroll dba.se 是什么?为什么要标记?
-
dba.stackexchange.com(以便管理员移动)
-
@EvanCarroll 以及您认为应该搬家的原因是什么?
-
更专业的 postgresql 和 postgis 用户群
标签: postgresql postgis