【发布时间】:2015-06-23 11:18:31
【问题描述】:
好的,我想我遇到了一个奇怪的问题,而且我一直在寻找答案。
我才开始:
我有一个设备表:
Column | Type | Modifiers
----------+-----------+------------------------------------------------------
id | integer | not null default nextval('devices_id_seq'::regclass)
location | geography |
radius | integer |
代表一堆设备的位置和位置分辨率。
我想查找区域范围内的设备。
所以,我可以进行如下查询:
SELECT count(id) FROM devices WHERE ST_intersects(ST_buffer(ST_GeographyFromText('POINT(-80.519142 43.460270)'), 20000), ST_buffer(location, radius));
硬编码位置最终来自连接。
所以,我有不确定的设备和一个很大的区域,我想知道哪些设备可能位于该区域内。 此查询有效,但在 100000 台设备的测试中,需要 28 秒。
所以我想索引它。 一整天了,我知道一些事情,但不是正确的答案。
首先,像CREATE INDEX device_buffer ON devices USING gist (st_buffer(location, radius)); 这样的索引似乎存在,但看看上面的查询,它实际上从未被使用过。
查看explain的输出,显示geography(st_transform(st_buffer(st_transform(geometry(location), _st_bestsrid(location, location)), (radius)::double precision), 4326)),好像是扩展版。
为此添加索引似乎也无济于事。
所以,为了弄清楚问题是ST_INTERSECT还是我,我做了:
CREATE MATERIALIZED VIEW device_buffer_view AS SELECT id, ST_BUFFER(location, radius) as buffer FROM devices;
并在该视图的缓冲区字段上放置一个索引。 该查询命中索引。 好的。 这告诉我,我的缓冲区可以在交叉路口建立索引。
但这仍然不是很好,因为我实际上并不想要物化视图。
不过,我想要表格中的位置和半径,因为应用程序的其他部分会查看此数据,并允许稍后对其进行调整。只存储生成的 Geography 是没有帮助的。
根据我在网上找到的东西,我尝试了:
CREATE FUNCTION geog(rec devices) RETURNS geography IMMUTABLE LANGUAGE SQL AS 'SELECT ST_BUFFER($1.location, $1.radius);';
这允许我做SELECT devices.geog FROM devices,并将其编入索引,但放置一个如下索引:
CREATE INDEX device_geog ON devices USING GIST ((devices.geog));
在选择查询中使用devices.geog 时效果不会更好。
所以,看来我可能必须将地理位置存储在表中,这很好,然后我可以索引它。
不过,我不希望它被非规范化。
我尝试制定一个规则,以便如果位置或半径有更新,它会自动重新计算存储的地理,但它抱怨递归规则...
那么,有没有什么非常简单的事情我没有触及,或者我错过了一些微妙的点?
我很困惑,有点沮丧,甚至可能超出了我的理解范围。
有什么想法吗?
【问题讨论】:
标签: postgresql indexing gis postgis