Próbuję obliczyć statystyki dla danych OSM za pomocą PostgreSQL 9.3.5 i PostGIS 2.1.4. Zacząłem od małego wyciągu z bawarii, który pobrałem z Geofabrik. Schemat db jest normalnym schematem API 0.6, dane zostały zaimportowane za pomocą zrzutu do Postgres (za pomocą skryptów pgsnapshot_schema_0.6 * .sql, które są dostarczane z osmozą). Wykonano również PODCIŚNIENIE ANALIZOWE.
Jedyną niestandardową rzeczą, której używam, jest tabela wielokątów, która zawiera wieloboki dla wszystkich relacji granic administracyjnych. Geometria wielokąta nie została w żaden sposób uproszczona.
To, co teraz próbuję osiągnąć, to zliczenie wszystkich węzłów, które znajdują się w admin = 6 granicach bawarii. Oto moje zapytanie 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;
Środowisko wykonawcze tego zapytania jest straszne, ponieważ Postgres wykonuje zagnieżdżone sprzężenie pętli i skanuje wszystkie węzły pod kątem każdej granicy admin = 6. Do Twojej wiadomości, Bawaria jest podzielona na 98 admin = 6 wielokątów, aw ekstrakcie z bawarii znajduje się około 30 milionów węzłów.
Czy można uniknąć tego nieoptymalnego wykonania zapytania i powiedzieć Postgresowi, że powinien skanować wszystkie węzły tylko raz (np. Zwiększając licznik dla odpowiedniego wielokąta w zestawie wyników lub używając wskazówek)?
Edytować:
1) w węzłach bawarii istnieje indeks przestrzenny:
CREATE INDEX idx_nodes_geom ON bavaria.nodes USING gist (geom);
2) plan zapytań wygląda następująco:
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)
Utworzyłem następujące dwa indeksy, ale plan zapytań (i środowisko wykonawcze) nie zmieniły się
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
i admin_level
) do dodatkowych kolumn w tabeli i użyj ich bezpośrednio.