Postgres ST_Distance - запрос на лучшую производительность, который находит ближайшие точки - PullRequest
0 голосов
/ 17 октября 2019

В настоящее время у меня есть этот запрос

SELECT "Id" 
FROM "Point" 
WHERE ST_Distance(ST_SetSRID(ST_Point("Longitude", "Latitude"), 4326)::geography, 
                  ST_SetSRID(ST_Point(@longitudeOfA, @latitudeOfA), 4326)::geography) <= @MaxDistance 
LIMIT 1

Как вы видите, я не храню пространственные данные в своей таблице точек, а скорее создаю их в операторе выбора запроса (ST_Point) со столбцами широты и долготы.

Цель этого запроса - проверить, есть ли хотя бы одна точка радиуса @ MaxDistance.

Боюсь, что для каждой записи при выполнении этого запроса выбора я создаю ST_Point.

По крайней мере, знаю, что записей не так много, поэтому производительность будет достаточной, но, боюсь, она станет очень дорогой, когда будет много записей Point из-за создания ST_Pin для каждой записи.

Из-за некоторых ограничений я не могу создать таблицу пространственных данных в точке.

1 Ответ

1 голос
/ 17 октября 2019

Этот запрос не может быть эффективным с большим количеством точек. Не потому, что он должен создавать географию, а потому, что st_distance не использует пространственные индексы.

Я бы лично создал геометрию или географию, поскольку с ними легко работать (функции PostGIS).

Важным является пространственный индекс. В вашем случае без столбца геометрия / география вы создали бы индекс функции

create index spatialIDX on mytable using gist(ST_SetSRID(ST_Point("Longitude", "Latitude"), 4326)::geography);

, а затем изменили запрос на использование ST_DWithin, в котором используется индекс.
Не забудьте также заказать по расстоянию, иначе вы получите случайную точку на нужном расстоянии. (Обратите внимание, что оператор <-> использует индекс, но он должен быть создан на геометрическом поле, а не на географии. Вы также можете положиться на st_distance в предложении упорядочения. Если у вас мало точек длязаказать, либо в порядке. Еще, создать индекс по геометрии)

SELECT "Id" 
FROM "Point" 
WHERE ST_DWithin(ST_SetSRID(ST_Point("Longitude", "Latitude"), 4326)::geography, 
                 ST_SetSRID(ST_Point(@longitudeOfA, @latitudeOfA), 4326)::geography,
                 @MaxDistance) 
ORDER BY  ST_SetSRID(ST_Point("Longitude", "Latitude"), 4326) <-> ST_SetSRID(ST_Point(@longitudeOfA, @latitudeOfA), 4326)
LIMIT 1;
...