Я использую PostreSQL 9.3 с PostGIS 2.1.8 на Amazon RDS. У меня есть таблица с именем project_location, в которой определяются «геозоны» (каждая из которых, по сути, является координатой и радиусом). Геозона сохраняется с использованием столбца геометрии с именем «местоположение» и двойного столбца с именем «радиус». У меня есть пространственный индекс в столбце местоположения.
CREATE TABLE project_location
(
...
location geography(Point,4326),
radius double precision NOT NULL,
...
)
CREATE INDEX gix_project_location_location
ON project_location USING gist (location);
В таблице сейчас ~ 50 000 записей. Если я запрошу таблицу, чтобы найти все project_locations, в которых геозона содержит точку, что-то вроде
SELECT COUNT(*)
FROM project_location
WHERE ST_DWithin(location, ST_SetSRID(ST_MakePoint(-84.1000, 34.0000),4326)::geography, radius);
Я считаю, что пространственный индекс не используется. Результаты EXPLAIN показывают следующее:
"Aggregate (cost=11651.97..11651.98 rows=1 width=0)"
" -> Seq Scan on project_location (cost=0.00..11651.97 rows=1 width=0)"
" Filter: ((location && _st_expand('0101000020E610000066666666660655C00000000000004140'::geography, radius)) AND ('0101000020E610000066666666660655C00000000000004140'::geography && _st_expand(location, radius)) AND _st_dwithin(location, '0101000020E610000066666666660655C00000000000004140'::geography, radius, true))"
Однако, если радиус является постоянным значением, как в следующем
SELECT COUNT(*)
FROM project_location
WHERE ST_DWithin(location, ST_SetSRID(ST_MakePoint(-84.1000, 34.0000),4326)::geography, 1000);
Пространственный индекс используется, как показано EXPLAIN
"Aggregate (cost=8.55..8.56 rows=1 width=0)"
" -> Index Scan using gix_project_location_location on project_location (cost=0.28..8.55 rows=1 width=0)"
" Index Cond: (location && '0101000020E610000066666666660655C00000000000004140'::geography)"
" Filter: (('0101000020E610000066666666660655C00000000000004140'::geography && _st_expand(location, 1000::double precision)) AND _st_dwithin(location, '0101000020E610000066666666660655C00000000000004140'::geography, 1000::double precision, true))"
Прочитав, как ST_DWithin использует индексы, я понимаю, почему это так. По сути, ограничивающая рамка на основе радиуса используется для «предварительной фильтрации» точек-кандидатов для определения возможных совпадений перед выполнением относительно дорогостоящего вычисления расстояния для этих точек.
Мой вопрос, есть ли способ выполнить этот тип поиска, чтобы можно было использовать пространственный индекс? В принципе, способ запроса таблицы с кучей геозон переменного радиуса?
ST_DWithin
, это вопрос о планировщике (или отправке функции pg) - person Evan Carroll   schedule 01.12.2016