Hstore键/值和空间查询的组合太慢,无法处理更大的OSM提取


13

我正在尝试使用PostgreSQL 9.3.5和PostGIS 2.1.4计算OSM数据的一些统计信息。我从从Geofabrik下载的巴伐利亚提取物开始。db模式是正常的API 0.6模式,数据是通过转储方法导入到Postgres中的(使用渗透性附带的pgsnapshot_schema_0.6 * .sql脚本)。还进行了真空分析。

我使用的唯一定制产品是一个多边形表,该表包含用于所有管理边界关系的多面体。多边形的几何形状没有任何简化。

我现在想要实现的是计算巴伐利亚的admin = 6边界内的所有节点。这是我的SQL查询:

SELECT relpoly.id, count(node) 
FROM bavaria.relpolygons relpoly, bavaria.nodes node
WHERE relpoly.tags @> '"boundary"=>"administrative","admin_level"=>"6"'::hstore 
AND ST_Intersects(relpoly.geom, node.geom)
GROUP BY relpoly.id;

该查询的运行时非常糟糕,因为Postgres正在执行嵌套循环联接,并在所有节点上扫描每个admin = 6边界。仅供参考,巴伐利亚被分成98个admin = 6个多边形,巴伐利亚提取物中大约有3000万个节点。

是否有可能避免这种次优查询的执行,并告诉Postgres它只扫描一次所有节点(例如,通过增加结果集中对应多边形的计数器或使用提示)?

编辑:

1)巴伐利亚节点上存在空间索引:

CREATE INDEX idx_nodes_geom ON bavaria.nodes USING gist (geom);

2)查询计划如下:

HashAggregate  (cost=284908.49..284908.75 rows=26 width=103)
  ->  Nested Loop  (cost=111.27..283900.80 rows=201537 width=103)
        ->  Bitmap Heap Scan on relpolygons relpoly  (cost=4.48..102.29 rows=26 width=5886)
              Recheck Cond: (tags @> '"boundary"=>"administrative", "admin_level"=>"6"'::hstore)
              ->  Bitmap Index Scan on relpolygons_geom_tags  (cost=0.00..4.47 rows=26 width=0)
                    Index Cond: (tags @> '"boundary"=>"administrative", "admin_level"=>"6"'::hstore)
        ->  Bitmap Heap Scan on nodes node  (cost=106.79..10905.50 rows=983 width=127)
              Recheck Cond: (relpoly.geom && geom)
              Filter: _st_intersects(relpoly.geom, geom)
              ->  Bitmap Index Scan on idx_nodes_geom  (cost=0.00..106.55 rows=2950 width=0)
                    Index Cond: (relpoly.geom && geom)

3)

我创建了以下两个索引,但是查询计划(和运行时)没有改变

CREATE INDEX relpolygons_tags_boundary on bavaria.relpolygons( (tags->'boundary') );
CREATE INDEX relpolygons_tags_admin on bavaria.relpolygons( (tags->'admin_level') );
ANALYZE bavaria.relpolygons;

1
在bavaria.nodes中有空间索引吗?
user30184

是的,我已经编辑了问题,并提供了有关节点索引和查询计划的信息
Alf Kortig 2015年

3
两种选择。1-为hstore标签添加索引。2-将您用于查询的标记(boundaryadmin_level)提取到表的其他列中,然后直接使用它们。
BradHards 2015年

请参阅编辑(3):添加了两个索引,但是查询计划和运行时均未更改。
Alf Kortig 2015年

经过一些测试后,我不确定在(3)中是否创建了正确的索引。到目前为止,我设法为->和?创建了索引。hstore运算符。但是,我在查询中使用@>
Alf Kortig 2015年

Answers:


5

索引hstore标签的最佳方法是使用GIN或GIST索引,它们从docs开始支持@>,?,?&和?|。运算符,即搜索键和键/值对。您使用函数来提取B树索引的标签的方法是合理的,但是由于您还要检查特定的键/值对,因此分析器选择了全表扫描。

我没有访问bavaria.relpolygons的权限,但是基于对OSM UK的速度限制和高速公路标签的类似查询,我可以通过以下查询对此进行解释:

SELECT count(*) 
 FROM ways 
WHERE tags @> 'highway=>motorway'::hstore 
 AND tags @> 'maxspeed=>"50 mph"'::hstore;


Aggregate  (cost=48.66..48.67 rows=1 width=0)
    ->  Index Scan using ix_ways_tags_gist on ways  (cost=0.42..48.64 rows=11 width=0)
     Index Cond: ((tags @> '"highway"=>"motorway"'::hstore) AND (tags @> '"maxspeed"=>"50 mph"'::hstore))

它显示了直接索引扫描(使用要点索引),对于具有1000万行的表,这是令人鼓舞的。索引的创建很简单:

CREATE INDEX ix_ways_tags_gist ON ways USING gist (tags);

虽然我无法检查您的空间状况,但我猜它的选择性不如

在哪里relpoly.tags @>'“ boundary” =>“ administrative”,“ admin_level” =>“ 6”':: hstore。

因此只能用于重新检查条件。

关于GIN和GIST索引之间的差异也有一个很好的SO答案。总的发现是,GIN索引虽然较大且构建较慢,但在文本检索问题上要快得多。

很抱歉回答这么晚,但是我最近在OSM和hstore上做过类似的工作,发现我不仅曾对此问题加注标,而且现在可以回答:D。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.