Ich versuche, mit PostgreSQL 9.3.5 und PostGIS 2.1.4 einige Statistiken für OSM-Daten zu berechnen. Ich habe mit einem kleinen Bayern-Extrakt angefangen, den ich von der Geofabrik heruntergeladen habe. Das DB-Schema ist das normale API 0.6-Schema. Die Daten wurden über den Dump-Ansatz in Postgres importiert (mithilfe der mit Osmose gelieferten Skripte pgsnapshot_schema_0.6 * .sql). ANALYSE VACUUM wurde ebenfalls durchgeführt.
Ich verwende nur eine Polygontabelle, die Multipolygone für alle administrativen Grenzbeziehungen enthält. Die Polygongeometrie wurde in keiner Weise vereinfacht.
Ich versuche jetzt, alle Knoten zu zählen, die innerhalb der Grenzen von admin = 6 von Bayern liegen. Hier ist meine SQL-Abfrage:
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;
Die Laufzeit dieser Abfrage ist furchtbar, da Postgres einen Join mit verschachtelten Schleifen ausführt und alle Knoten nach jeder Grenze von admin = 6 durchsucht. Zu Ihrer Information, Bayern ist in 98 Admin = 6 Polygone unterteilt und der Bayern-Extrakt enthält ungefähr 30 Millionen Knoten.
Ist es möglich, diese suboptimale Abfrageausführung zu vermeiden und Postgres mitzuteilen, dass alle Knoten nur einmal durchsucht werden sollen (z. B. durch Inkrementieren eines Zählers für das entsprechende Polygon in der Ergebnismenge oder durch Verwenden von Hinweisen)?
Bearbeiten:
1) Auf den Bayernknoten existiert ein räumlicher Index:
CREATE INDEX idx_nodes_geom ON bavaria.nodes USING gist (geom);
2) Der Abfrageplan sieht folgendermaßen aus:
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)
Ich habe die folgenden zwei Indizes erstellt, aber der Abfrageplan (und die Laufzeit) haben sich nicht geändert
CREATE INDEX relpolygons_tags_boundary on bavaria.relpolygons( (tags->'boundary') );
CREATE INDEX relpolygons_tags_admin on bavaria.relpolygons( (tags->'admin_level') );
ANALYZE bavaria.relpolygons;
boundary
und admin_level
) verwenden, in zusätzliche Spalten in der Tabelle und verwenden Sie diese direkt.