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;
la source
boundary
etadmin_level
) dans des colonnes supplémentaires sur la table et utilisez-les directement.Réponses:
La meilleure façon d'indexer les balises hstore est d'utiliser les index GIN ou GIST qui, à partir des documents , prennent en charge les @>,?,? & Et? | opérateurs , qui est, les recherches sur les clés et les paires clé / valeur. Votre approche de l'utilisation d'une fonction pour extraire les balises d'un index B-tree est raisonnable, mais parce que vous vérifiez également des paires clé / valeur spécifiques, l'analyseur a choisi une analyse complète de la table.
Je n'ai pas accès à bavaria.relpolygons, mais sur la base d'une requête similaire pour OSM UK sur les limites de vitesse et les balises d'autoroute, je l'obtiens pour mon explication sur la requête suivante:
qui montre un balayage d'index direct (en utilisant l'index gist), ce qui est encourageant pour une table avec 10 millions de lignes. L'index a été créé avec le simple:
Bien que je ne puisse pas vous vérifier la condition spatiale, je suppose que c'est moins sélectif que
et ne serait donc utilisé que pour une condition de revérification.
Il y a aussi cette excellente réponse SO sur la différence entre les indices GIN et GIST . La conclusion générale est que les index GIN, bien que plus grands et plus lents à construire, sont beaucoup plus rapides en cas de problèmes de récupération de texte.
Désolé de répondre si tard, mais j'ai récemment effectué un travail similaire sur OSM et hstore, et j'ai découvert que non seulement j'ai une fois posé cette question, mais que je pouvais maintenant y répondre: D.
la source