Оптимизация очень большой точки в запросе многоугольника

9

У меня есть национальный набор данных точек адреса (37 миллионов) и набор данных полигонов контуров наводнения (2 миллиона) типа MultiPolygonZ, некоторые из полигонов очень сложные, максимальное значение ST_NPoints составляет около 200 000. Я пытаюсь с помощью PostGIS (2.18) определить, какие адресные точки находятся в многоугольнике затопления, и записать их в новую таблицу с идентификатором адреса и подробностями риска затопления. Я попытался с точки зрения адресации (ST_Within), но затем поменял его местами, начиная с точки зрения зоны затопления (ST_Contains), обосновывая это тем, что есть большие территории, где вообще нет риска затопления. Оба набора данных были перепроектированы в 4326, и обе таблицы имеют пространственный индекс. Мой запрос ниже выполнялся в течение 3 дней и не показывает никаких признаков завершения в ближайшее время!

select a.id, f.risk_factor_1, f.risk_factor_2, f.risk_factor_3
into gb.addresses_with_flood_risk
from gb.flood_risk_areas f, gb.addresses a
where ST_Contains(f.the_geom, a.the_geom);

Есть ли более оптимальный способ запустить это? Кроме того, для долго выполняющихся запросов этого типа, каков наилучший способ мониторинга прогресса, кроме рассмотрения использования ресурсов и pg_stat_activity?


Мой первоначальный запрос был выполнен нормально, хотя и в течение 3 дней, и я отвлекся на другую работу, поэтому мне не удавалось посвятить время поиску решения. Тем не менее, я только что посетил это и проработал рекомендации, пока все хорошо. Я использовал следующее:

  1. Создал 50-километровую сетку над Великобританией, используя предложенное здесь решение ST_FishNet.
  2. Задайте для SRID сгенерированной сетки значение British National Grid и создайте на ней пространственный индекс
  3. Подрезал мои данные потока (MultiPolygon), используя ST_Intersection и ST_Intersects (здесь я понял, что мне нужно было использовать ST_Force_2D для geom, так как shape2pgsql добавил индекс Z
  4. Подрезал мои точечные данные, используя ту же сетку
  5. Созданные индексы для строки и столбца и пространственный индекс для каждой из таблиц

Я готов запустить свой сценарий сейчас, буду перебирать строки и столбцы, заполняя результаты в новую таблицу, пока не охватлю всю страну. Но только что проверил мои данные о потопе, и некоторые из самых больших полигонов, похоже, были потеряны в переводе! Это мой запрос:

SELECT g.row, g.col, f.gid, f.objectid, f.prob_4band, ST_Intersection(ST_Force_2D(f.geom), g.geom) AS geom 
INTO rofrse.tmp_flood_risk_grid 
FROM rofrse.raw_flood_risk f, rofrse.gb_grid g
WHERE (ST_Intersects(ST_Force_2D(f.geom), g.geom));

Мои исходные данные выглядят так:

Исходные данные о наводнениях

Однако после обрезки это выглядит так:

Сетевые данные о наводнениях

Это пример «отсутствующего» многоугольника:

«Пропавший» многоугольник

Марк Варли
источник
Я только что понял, что мы встретились на FOSS4G в Сеуле и поговорили о чудесах локатора ESRI :-)
Джон Пауэлл,
Вы когда-нибудь заканчивали подход «разделяй и властвуй»? Можете ли вы обновить время тестов с помощью этого подхода?
Андрей

Ответы:

6

Чтобы ответить на ваш последний вопрос, сначала посмотрите этот посто желательности возможности отслеживать ход выполнения запросов. Эта проблема сложна и может быть усугублена в пространственном запросе, поскольку знание того, что 99% адресов уже были отсканированы на наличие содержимого в многоугольнике потока, который можно получить из счетчика циклов в базовой реализации сканирования таблицы, не обязательно помогите, если последние 1% адресов пересекают многоугольник наводнения с наибольшим количеством точек, в то время как предыдущие 99% пересекают небольшую область. Это одна из причин, почему EXPLAIN иногда может оказаться бесполезным с пространственным, поскольку он дает указание строк, которые будут сканироваться, но, по очевидным причинам, не учитывает сложность многоугольников (и, следовательно, большую долю времени выполнения) любых запросов на пересечение / тип пересечения.

Вторая проблема заключается в том, что если вы посмотрите на что-то вроде

EXPLAIN 
SELECT COUNT(a.id) 
FROM sometable a, someothertable b
WHERE ST_Intersects (a.geom, b.geom)

Вы увидите что-то вроде, пропустив много деталей:

_st_intersects(a.geom, b.geom)
   ->  Bitmap Index Scan on ix_spatial_index_name  (cost...rows...width...))
   Index Cond: (a.geom && geom)

Конечное условие && означает проверку ограничивающего прямоугольника, прежде чем делать более точное пересечение фактических геометрий. Это очевидно разумно и лежит в основе работы R-Trees. Однако в прошлом я также работал с данными о наводнениях в Великобритании, поэтому знаком со структурой данных, если (много) многоугольники очень обширны - эта проблема особенно остра, если река протекает, скажем, 45 градусы - вы получаете огромные ограничивающие рамки, которые могут заставить проверяться огромное количество потенциальных пересечений на очень сложных полигонах.

Единственное решение, которое мне удалось найти для решения проблемы «мой запрос выполняется 3 дня, и я не знаю, находимся ли мы на уровне 1% или 99%», - это использовать своего рода «разделяй и властвуй» для манекенов Подход, под которым я подразумеваю, разбейте вашу область на более мелкие куски и запустите их по отдельности, либо в цикле в plpgsql, либо явно в консоли. Это имеет преимущество в разрезании сложных многоугольников на части, что означает, что последующие точки при проверке многоугольников работают на меньших многоугольниках, а ограничивающие рамки многоугольников намного меньше.

Мне удалось выполнить запросы за один день, разбив Великобританию на блоки по 50 км на 50 км, после уничтожения запроса, который выполнялся более недели по всей Великобритании. Кроме того, я надеюсь, что ваш запрос выше - CREATE TABLE или UPDATE, а не просто SELECT. Когда вы обновляете одну таблицу, адреса, исходя из того, что вы находитесь в многоугольнике потока, вам все равно придется сканировать всю обновляемую таблицу, адреса, так что фактически наличие пространственного индекса для нее вообще не поможет.

РЕДАКТИРОВАТЬ: Исходя из того, что изображение стоит тысячи слов, вот изображение некоторых данных наводнения Великобритании. Существует один очень большой мультиполигон, ограничивающий прямоугольник которого охватывает всю эту область, поэтому легко увидеть, как, например, при первом пересечении полигона с красной сеткой квадрат в юго-западном углу внезапно будет проверен против крошечного подмножества многоугольника.

введите описание изображения здесь

Джон Пауэлл
источник
Привет, Джон, и большое спасибо за исчерпывающий ответ, я последую твоей рекомендации по сеточному подходу, звучит как очень разумное предложение, я действительно не хочу упрощать и терять точность. Я проведу сравнительный анализ с одним блоком, а затем буду работать параллельно, в эти дни намного проще с облаком! Еще раз спасибо
Марк Варли
Привет Марк, не беспокойтесь, пожалуйста, примите ответ, если считаете, что он помог. Это помогает содержать сайт в чистоте, вопросы без принятых ответов являются одной из метрик, на которые смотрят сайты обмена.
Джон Пауэлл
ОК, все готово, это мой первый пост здесь, я обычно нахожу ответ из подробных тем и полезных ответов. Запрос, наконец, завершился сегодня утром, примерно через 3 дня, что не так уж и плохо, но мы последуем вашему совету сегодня и разделим его на куски для повышения производительности. Еще раз спасибо за вашу помощь Джон и, возможно, увидимся в Бонне в августе!
Марк Варли
Я добавил фотографию, хотя я понимаю, что у вас есть фотография: D, она может помочь другим представить, о чем я. Да, я почти наверняка собираюсь в Foss4G UK, и буду думать о Бонне.
Джон Пауэлл