Я пытаюсь вычислить статистику для данных OSM, используя PostgreSQL 9.3.5 и PostGIS 2.1.4. Я начал с небольшого экстракта баварии, который я скачал с 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 полигонов, и в экстракте Баварии находится около 30 миллионов узлов.
Можно ли избежать этого неоптимального выполнения запроса и сказать 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;
boundary
и admin_level
), в дополнительные столбцы таблицы и используйте их напрямую.