Проблема с индексацией в postgres
не получается ускорить БД за счёт индексации.
Создаю таблицу:
CREATE TABLE IF NOT EXISTS coordinate( Id serial primary key,
Lat DECIMAL(9,6),
Lon DECIMAL(9,6));
После этого добавляю индексацию:
CREATE INDEX indeLat ON coordinate(Lat);
CREATE INDEX indeLon ON coordinate(Lon);
Потом идёт заполнение таблицы:
INSERT INTO coordinate (Lat, Lon) VALUES(48.685444, 44.474254)
Заполняется 100к рандомных координат.
Теперь мне нужно выдать все координаты которые входят в радиус N км от заданной координаты.
SELECT id, Lat, Lon
FROM coordinate
WHERE acos(sin(radians(48.704578))*sin(radians(Lat)) + cos(radians(48.704578))*cos(radians(Lat))*cos(radians(Lon)-radians(44.507112))) * 6371 < 50;
Время выполнения тестов, примерно равно 0.2сек, причём если не делать CREATE INDEX время не изменяется. Подозреваю что ошибка в запросе, может нужно как то перестроить?
Ответы (1 шт):
А каким волшебным образом, вы полагаете, вам здесь могут помочь два btree? На пальцах - каков алгоритм? Правильно, никакой. Единственная возможность - вычислить выражение для каждой строки. Для чего seqscan и выбирается.
В общем случае индекс может использоваться только в выражениях indexcolumn operator const. Любой function(indexcolumn) operator const индекс по indexcolumn использовать уже не сможет, т.к. где результат этой функции? Его вычислять надо прежде чем сравнивать. (но может - индекс по выражению function(indexcolumn) если функция immutable)
Для адекватного решения задачи поиска по географическим координатам вам нужен postgis и конкретно функция ST_DWithin, а так же gist индекс.
select ... from tablename where ST_DWithin(geom, /*ваша geom точка*/, /*радиус*/)