J'essaie de calculer des statistiques pour les données OSM en utilisant PostgreSQL 9.3.5 et PostGIS 2.1.4. J'ai commencé avec un petit extrait de Bavière que j'ai téléchargé sur Geofabrik. Le schéma db est le schéma API 0.6 normal, les données ont été importées via l'approche de vidage dans Postgres (en utilisant les scripts pgsnapshot_schema_0.6 * .sql fournis avec l'osmose). ANALYSER LE VIDE a également été réalisé.
La seule chose sur mesure que j'utilise est une table de polygones qui contient des multipolygones pour toutes les relations de limites administratives. La géométrie du polygone n'a été simplifiée en aucune façon.
Ce que j'essaie maintenant d'atteindre, c'est de compter tous les nœuds qui se trouvent à l'intérieur des limites admin = 6 de la Bavière. Voici ma requête 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;
L'exécution de cette requête est terrible car Postgres effectue une jointure de boucle imbriquée et analyse tous les nœuds pour chaque limite admin = 6. Pour info, la bavière est divisée en 98 admin = 6 polygones et il y a environ 30 millions de nœuds dans l'extrait de bavière.
Est-il possible d'éviter cette exécution de requête sous-optimale et de dire à Postgres de ne scanner tous les nœuds qu'une seule fois (par exemple, en incrémentant un compteur pour le polygone correspondant dans le jeu de résultats ou en utilisant des astuces)?
Éditer:
1) un indice spatial existe sur les nœuds bavarois:
CREATE INDEX idx_nodes_geom ON bavaria.nodes USING gist (geom);
2) le plan de requête ressemble à ceci:
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)
J'ai créé les deux index suivants, mais le plan de requête (et le runtime) n'ont pas changé
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
et admin_level
) dans des colonnes supplémentaires sur la table et utilisez-les directement.