Оптимизация Sqlite-запроса для INDEX - PullRequest
2 голосов
/ 25 июля 2010

У меня есть таблица из 320000 строк, которая содержит координаты широты / долготы. Когда пользователь выбирает местоположение, моя программа получает координаты из выбранного местоположения и выполняет запрос, который приносит все точки из таблицы, которые находятся рядом. Это делается путем вычисления расстояния между выбранной точкой и каждой координатной точкой из строки моей таблицы. Это запрос, который я использую:

select street from locations 
where (  ( (lat - (-34.594804)) *(lat - (-34.594804)) ) + ((lon - (-58.377676 ))*(lon - (-58.377676 ))) <= ((0.00124)*(0.00124))) 
group by street;

Как видите, предложение WHERE представляет собой простую формулу Пифагора для вычисления расстояния между двумя точками. Теперь моя проблема в том, что я не могу получить ИНДЕКС, чтобы его можно было использовать. Я пробовал с

CREATE INDEX indx ON location(lat,lon) 

также с

CREATE INDEX indx ON location(street,lat,lon) 

без удачи. Я заметил, что когда есть математическая операция с lat или lon, индекс не вызывается. Можно ли как-нибудь оптимизировать этот запрос для использования индекса, чтобы получить результаты скорости?

Заранее спасибо!

Ответы [ 4 ]

2 голосов
/ 23 февраля 2012

Проблема заключается в том, что движку sql необходимо оценить все записи, чтобы выполнить сравнение (WHERE ..... <= ...) и отфильтровать точки, чтобы индексы не ускоряли запрос.Одним из подходов к решению проблемы является вычисление минимальной и максимальной широты и долготы, чтобы ограничить количество записей.Вот хорошая ссылка: <a href="http://janmatuschek.de/LatitudeLongitudeBoundingCoordinates" rel="nofollow"> Поиск точек на расстоянии широты / долготы

1 голос
/ 25 июля 2010

Вы пытались настроить размер страницы ? Такая таблица может выиграть от наличия другого (т.е. самого большого?) Доступного размера страницы.

PRAGMA page_size = 32768;

Или любое значение 2 от 512 до 32768. Если вы измените размер страницы, не забудьте очистить базу данных (если вы используете SQLite 3.5.8. В противном случае вы не сможете изменить ее и потребуется запустить новая новая база данных).

Кроме того, выполнение операции над числами с плавающей запятой может быть не таким быстрым, как выполнение операции над целыми числами (возможно, большим), так что вы можете набрать скорость, если вы запишите все свои координаты, умноженные на 1 000 000.

Наконец, евклидово расстояние не даст очень точных результатов близости. Чем дальше вы находитесь от экватора, тем больше круг вокруг вашей точки будет сглаживаться, образуя эллипс. Существуют быстрые аппроксимации, которые не настолько интенсивны, как расчет расстояния большого круга (избегайте любой ценой!)

1 голос
/ 02 августа 2011

Вы должны искать в квадрате вместо круга. Тогда вы сможете оптимизировать.

0 голосов
/ 25 июля 2010

Наверняка у вас есть первичный ключ в локациях?Возможно, называется id?

Почему бы просто не выбрать идентификатор вместе с улицей?

select id, street from locations 
where (  ( (lat - (-34.594804)) *(lat - (-34.594804)) ) + ((lon - (-58.377676 ))*(lon - (-58.377676 ))) <= ((0.00124)*(0.00124))) 
group by street;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...