Я намагаюся обчислити деяку статистику для даних OSM за допомогою PostgreSQL 9.3.5 та PostGIS 2.1.4. Я почав з невеликого екстракту баварії, який я завантажив з Geofabrik. Схема db - це звичайна схема API 0.6, дані були імпортовані за допомогою дамп-підходу до Postgres (використовуючи сценарії pgsnapshot_schema_0.6 * .sql, які поставляються з осмосом). АНАЛІЗОВИЙ ВАКУУМ також був виконаний.
Єдине, що я використовую на замовлення, - це полігонна таблиця, яка містить багатополігони для всіх адміністративних граничних відносин. Геометрію багатокутника жодним чином не спрощували.
Зараз я намагаюся досягти підрахунку всіх вузлів, які знаходяться всередині адміністратора = 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 робить вкладений цикл з'єднання та сканує всі вузли для кожного адміністратора = 6 кордонів. Здійснюється, баварія ділиться на 98 адмін = 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
), у зайві стовпці таблиці та використовуйте їх безпосередньо.