Я пытаюсь вычислить статистику для данных 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
), в дополнительные столбцы таблицы и используйте их напрямую.Ответы:
Лучший способ индексировать теги hstore - использовать индексы GIN или GIST, которые из документов поддерживают @>,?,? & И? | операторы , то есть поиск по ключам и парам ключ / значение. Вы подходите к использованию функции для извлечения тегов для индекса B-дерева разумно, но поскольку вы также проверяете конкретные пары ключ / значение, анализатор выбрал полное сканирование таблицы.
У меня нет доступа к bavaria.relpolygons, но на основе аналогичного запроса для OSM UK по ограничениям скорости и тегам шоссе я получу это для своего объяснения по следующему запросу:
который показывает прямое сканирование индекса (с использованием индекса gist), что для таблицы с 10 миллионами строк обнадеживает. Индекс был создан с простым:
Хотя я не могу проверить ваше пространственное состояние, я предполагаю, что оно менее избирательно, чем
и поэтому будет использоваться только для условия перепроверки.
Существует также отличный ответ SO на разницу между индексами GIN и GIST . Общий вывод заключается в том, что индексы GIN, хотя они больше и медленнее создаются, намного быстрее справляются с проблемами поиска текста.
Извините, что отвечаю так поздно, но недавно я выполнял аналогичную работу над OSM и hstore, и обнаружил, что я не только однажды поставил этот вопрос, но и теперь могу ответить на него: D.
источник