Выполнять ограничивающий запрос в PostGIS? [закрыто]

22

У меня есть таблица PostgreSQL, с почти 2 миллионами строк, с coordinatesполем long-lat в форме POINT(-73.4938 33.2405).

Предположим, что в этом поле есть геопространственный индекс. Какой самый эффективный и быстрый способ выделить все строки в произвольной ограничительной рамке?

Коробка , как SW long-lat: -74.0042 40.7688, NE long-lat: -73.8809 40.7984.

Avishai
источник
Ваши сохраненные координаты уже длинные-лат или сетка (X, Y)?
Мартин Ф
1
Здесь бы пригодилась простая математика ... Если point.x больше, чем SW.x и меньше, чем NE.x, а point.y больше, чем SW.y и меньше, чем NE.y, то точка находится внутри MBR. Я не знаю, быстрее ли это, чем использовать пространственный запрос. Вы не против попробовать?
Михал Циммерманн
@zimmi: На самом деле он не утверждает, что предметы - это просто очки; они могут быть сложной геометрии.
Мартин Ф
Они являются только точки, хотя ;-). Они long-lat в форме POINT (-73.4938 33.24059) и хранятся в виде WKB.
Avishai
Я отредактировал Q (и мой A), чтобы отразить эту информацию. :-)
Мартин Ф

Ответы:

24

Предполагая, что заданные пределы ограничительной рамки находятся в той же системе пространственной привязки, что и сохраненные координаты, и вы знаете, какой пространственный оператор (пересекающийся или содержащийся) вам нужен:

SELECT *
FROM   my_table
WHERE  coordinates 
    && -- intersects,  gets more rows  -- CHOOSE ONLY THE
    @ -- contained by, gets fewer rows -- ONE YOU NEED!
    ST_MakeEnvelope (
        xmin, ymin, -- bounding 
        xmax, ymax, -- box limits
        my_srid)

В качестве альтернативы, если вы предпочитаете звук «содержит» (вместо «содержится в»), WHEREпредложение должно быть перевернуто:

WHERE  ST_MakeEnvelope (...)
    ~ -- contains, gets same fewer rows 
    coordinates 

PS: Учитывая (по OP после того, как выше было опубликовано), что записи являются простыми точками, я думаю, что разница между «пересечениями» и «сдерживанием» становится очень тонкой, затрагивая только точки на краях ограничительной рамки.

Мартин Ф
источник
неплохо подмечено. С содержимым должно быть все в порядке, поскольку вы не сможете увидеть маркер карты, если он находится на границе (т. Е., Вероятно, браузер Chrome).
Авишай
What's the fastest ...?: OP
Magno C
Имейте в виду: &&и @, кажется, не работает при пересечении с геометрией многоугольника. В этом случае используйте ST_Intersects(latlng_column,ST_GeomFromText('Polygon ((...))',4326))или альтернативноST_Contains
Alex
4
SELECT ST_Y(the_geom) AS latitude, ST_X(the_geom) as longitude
from units u where the_geom && ST_MakeEnvelope(left, bottom, right, top, 4326)
Магно С
источник
1
Не обязательно говорить, что 4326 - это SRID.
Магно C
2

Очевидно, у меня недостаточно очков, чтобы добавить комментарий, поэтому я использую этот ответ только для того, чтобы сказать, что я попробовал и ST_MakeEnvelope, и сравнение по математике: «x> min_x и x <max_x и y> min_y и y <max_y». ..в среднем ST_MakeEnvelope заняло 60 мс, а сравнение по математике заняло 155 мс на моем конкретном запросе bbox.

Таким образом, пространственный поиск ST_MakeEnvelope должен быть быстрее, чем математическое сравнение!

Джейсон
источник
1
На самом деле, если вы создадите правильные индексы, min_x, max_x, min_y и max_y будут намного быстрее. У меня есть очень большой набор данных (более 3 миллионов полигонов), и я работал как INDEXс ST_MakeEnvelope, так и с (ST_XMax, ST_XMin, ST_YMax, ST_YMin), и разница огромна в пользу математики. Математика заняла у меня менее 20 секунд (INDEX + Query), в то время как пересечение огибающей заняло 2 минуты (я сдался, когда оно достигло 2 минут, 40
секунд