Как приложение выполняет поиск по близости? Например, пользователь вводит почтовый индекс, а затем приложение перечисляет все предприятия в радиусе 20 миль, отсортированные по близости.
Я хочу построить что-то подобное на PHP и MySQL. Это правильный подход?
Это нормально? На шаге 3 я собираюсь вычислить близость для каждого запроса. Лучше ли иметь таблицу PROXIMITY, в которой указано расстояние между каждым бизнесом и несколькими ссылочными местоположениями?






Если записей достаточно, чтобы скорость имела значение, вот способ их заблаговременно проиндексировать.
Определите сетку ящиков со стороной примерно 20 миль. Сохраните номер корзины с записью каждого магазина. Во время поиска вычислите количество всех ячеек, которые пересекают радиус 20 миль от точки поиска. Затем извлеките все хранилища в любой из этих ящиков и продолжайте, как прежде.
Мы делаем это примерно для 1200 локаций. Я бы просто использовал формулу Хаверсина на лету, хотя, в зависимости от вашего приложения, было бы лучше сохранить ее в PHP вместо SQL. (Наша реализация находится в .net, поэтому ваш пробег может отличаться).
На самом деле наш самый большой недостаток в том, как мы это реализовали, заключается в том, что каждое вычисление (до недавнего времени) приходилось рассчитывать на уровне данных, который был мучительно медленным (когда я говорю медленно, я действительно имею в виду, что не мгновенно, это заняло секунду или около того. ), но это было связано с тем, что он должен был рассчитать расстояние для всех 1200 местоположений на основе предоставленного почтового индекса.
В зависимости от выбранного вами маршрута есть способы ускорить вычисление числового расстояния, просмотрев долготу и широту и удалив те, которые выходят за пределы заранее определенного диапазона (например, если вы просматриваете все адреса в пределах 20 миль, есть диапазон долготы, вы можете вычислить, в какой из адресов должны попасть все адреса, чтобы они находились на расстоянии 20 миль). Это может ускорить выполнение запроса, если это необходимо.
Фактически мы рассмотрели возможность сохранения всех возможных комбинаций в нашей базе данных. На самом деле это звучит так, как будто это может быть большое хранилище данных, но на самом деле это не так. С индексами это может быть довольно быстро, и вам не нужно беспокоиться об оптимизации алгоритма и т. д. Мы отказались от этого, потому что у нас было уравнение на C#, и оно позволяло нам кэшировать информацию, необходимую для выполнения всех вычислений в бизнес-уровень. Любой из них будет работать нормально, это просто вопрос ваших предпочтений.
Мы используем это для определения многих тысяч точек. Если вы выполняете это в SQL, важно иметь индекс в столбце Широта и Долгота. Мы пытались сделать это в SQL 2008 с пространственными индексами, но на самом деле не увидели ожидаемого увеличения производительности. Хотя, если вы хотите произвести вычисления на определенном расстоянии от ZIP, вам нужно подумать о том, собираетесь ли вы использовать центроид ZIP или многоугольное представление почтового индекса.
Haversine forumla - хорошее место для начала.
У нас не было проблем с производительностью при вычислении расстояния на лету, мы рассчитываем его заранее для некоторых приложений, где мы заранее знаем точки и будут иметь миллионы записей.
SELECT
[DistanceRadius]=
69.09 *
DEGREES(
ACOS(
SIN( RADIANS(latitude) )*SIN( RADIANS(@ziplat) )
+
COS( RADIANS(latitude) )*COS( RADIANS(@ziplat) )
*
COS( RADIANS(longitude - (@ziplon)) )
)
)
,*
FROM
table
) sub
WHERE
sub.DistanceRadius < @radius
См. Также штраф movable-type.co.uk/scripts/latlong.html#cosine-law