Я пытаюсь разработать пространственный SQL-запрос для всех уникальных точек в одном или нескольких заданных наборах полигонов. Я использую PostGIS на облачном VPS с 6 vCPU и 16 ГБ оперативной памяти. Рассматриваемый пространственный тест - ST_Contains в предложении WHERE. Набор полигонов - это приблизительно 40 000 уникальных геометрий, которые ограничивают набор данных точечных объектов 3,7 миллиона.
Моя проблема в том, что когда я создаю запрос с более чем 13 000 полигонов (а значит, 13 000 операторов SELECT), сервер PostGIS отвечает ERROR: stack depth limit exceeded"
HINT: Increase the configuration parameter "max_stack_depth"
.
Я хочу знать, почему и если у меня есть варианты обойти это.
Это часть упражнения по оптимизации. Я уже извлекаю геометрию многоугольника в виде отдельного SELECT для формирования требуемого SQL-запроса. Я хочу выполнить запрос, который проверяет набор многоугольников как один оператор SQL. До сих пор я строил подзапрос SELECT для каждого многоугольника, а затем UNION каждый вместе в качестве отправной точки. При компиляции запрос, использующий только 13 000 полигонов, составляет ~ 28 000 000 символов, что, на мой взгляд, намного меньше, чем предел оператора PostGIS SQL.
Я пробовал меньшие размеры и обнаружил, что есть нормальная производительность вплоть до приблизительного предела. Я достиг этого предела ранее, но, посоветовавшись с сообщением об ошибке, увеличил max_stack_depth приблизительно до размера, который возвращает ulimit -s. Насколько я понимаю, этот оператор SQL не является какой-либо рекурсивной функцией, которая, как я ожидаю, приведет к превышению глубины стека.
Также из моего чтения стека и памяти кучи я не могу понять, почему этот запрос перегружает стек, так как большая часть требуемых хранимых данных должна оказаться в куче. Я также ожидаю, что запрос будет выполняться последовательно при сборе результатов, но похоже, что PostGIS может сначала запустить все подстанции SELECT, а затем подсчитать результаты.
Я решил не пытаться объединить отдельные геометрии многоугольника в один многоугольник, поскольку они охватывают очень географически разнородную область (т. Е. Не сгруппированы в простую массу), которая, как я считаю, резко снизит выгоды от пространственной индексации.
Мой текущий рабочий SQL-скрипт следует шаблону (обрезан для соответствия этому посту):
SELECT * FROM point_table WHERE ST_Contains("poly1_geom_str", pt_geom_col)
UNION
SELECT * FROM point_table WHERE ST_Contains("poly2_geom_str", pt_geom_col)
UNION
....
SELECT * FROM point_table WHERE ST_Contains("polyN_geom_str", pt_geom_col);
Моя стратегия построения этого оператора SQL вряд ли будет решена? Есть ли альтернативная стратегия, которую я могу попробовать, чтобы избежать проблемы рекурсии?