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存根. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |