Я не могу заставить PostGIS 2.1 работать на PostgreSQL 9.3.5, чтобы использовать пространственный индекс даже для самых простых запросов. Весь набор данных составляет 8 миллионов точек (население граф сетки здесь) . Таблица создана как
CREATE TABLE points (
population DOUBLE PRECISION NOT NULL,
location GEOGRAPHY(4326, POINT) NOT NULL
)
CREATE INDEX points_gix ON points USING GIST(location);
Запросы так же просты, как они получают
SELECT SUM(population)
FROM points
WHERE ST_Distance(
location,
ST_GeographyFromText('SRID=4326; POINT(0 0)')
) < 1000
PostgreSQL всегда использует сканирование Seq для этого, я пробовал подмножество с 10000 точками - все еще сканирование Seq. Любые идеи?
Ответы:
ST_Distance фактически вычисляет расстояние между всеми парами точек, поэтому, как таковой, индекс не может быть использован. Таким образом, ваш запрос выполнит сканирование последовательности, а затем выберет те геометрии, которые меньше указанного вами расстояния. Вы ищете ST_DWithin , который использует индекс.
ST_Distance более полезна для упорядочения результатов, часто в сочетании с ORDER BY и / или LIMIT, которые были получены с запросами, использующими индекс.
источник
Как сказал @ JohnPowellakaBarça,
ST_DWithin()
это путь, когда вы хотите исправить .Однако в моем случае мне нужна только приблизительная оценка, поэтому она
ST_DWithin()
была слишком дорогой (в стоимости запроса) для моих нужд. Я использовал&&
иST_Expand(box2d)
(не путайте это сgeometry
версией) вместо этого. Пример:Что сразу станет очевидным, так это то, что мы имеем дело с градусами, а не с метрами, и используем ограничивающий прямоугольник вместо круга в сфероиде. В моем случае это сокращается с 24 мс до 2 мс (локально в SSD). Однако для моей производственной базы данных в AWS RDS PostgreSQL с параллельными соединениями и едва ли щедрыми квотами IOPS (100 IOPS) исходный
ST_DWithin()
запрос тратит слишком много IOPS и может выполняться более 2000 мс и намного хуже при исчерпании квоты IOPS.Это не для всех, но в случае, если вы можете пожертвовать некоторой точностью ради скорости (или сэкономить IOPS), тогда этот подход может быть для вас. Как видно из приведенных ниже планов запросов, по-
ST_DWithin
прежнему требуется пространственный фильтр внутри сканирования кучи растровых изображений в дополнение к повторной проверке Cond, в то время&&
как для геометрии блока не требуется фильтр, а используется только повторная проверка Cond.Я также заметил, что это
IS NOT NULL
важно, без него у вас останется худший план запроса. Кажется, что индекс GIST не достаточно умен для этого. (конечно, это не нужно, если ваша колонка естьNOT NULL
, в моем случае этоNULL
возможно)Таблица строк на 20000,
ST_DWithin(geography, geography, 100000, FALSE)
в ОЗУ AWS RDS 512 МБ с 300 IOPS:20000 строк таблицы
&&
иST_Expand(box2d)
512 МБ ОЗУ AWS RDS с 300 IOPS:Опять с более простым запросом:
Таблица строк на 20000,
ST_DWithin(geography, geography, 100000, FALSE)
в ОЗУ AWS RDS 512 МБ с 300 IOPS:20000 строк таблицы
&&
иST_Expand(box2d)
512 МБ ОЗУ AWS RDS с 300 IOPS:источник