Вопрос

Как приложение выполняет поиск близости? Например, пользователь вводит почтовый индекс, а затем приложение перечисляет все предприятия в радиусе 20 миль, упорядоченные по близости.

Я хочу построить что-то подобное в PHP и MySQL. Правильный ли этот подход?

<Ол>
  • Получите адреса для местоположений, которые меня интересуют, и сохраните в моей базе данных
  • Геокодировать все адреса с помощью службы геокодирования Google
  • Напишите запрос к базе данных, включающий формулу Хаверсайна, для поиска и упорядочения близости
  • Это нормально? На шаге 3 я собираюсь вычислить близость для каждого запроса. Лучше ли иметь таблицу PROXIMITY, в которой указывается расстояние между каждым предприятием и несколькими ссылочными местоположениями?

    Это было полезно?

    Решение

    Если записей достаточно, чтобы скорость имела значение, вот способ заранее их проиндексировать.

    Определите сетку бункеров около 20 миль на стороне. Сохраните номер корзины с каждой записью магазина. Во время поиска вычислите номера всех корзин, которые пересекают радиус в 20 миль от точки поиска. Затем извлеките все магазины в любом из этих бункеров и продолжайте как раньше.

    Другие советы

    Мы используем это, чтобы заработать много тысяч очков. Важно, если вы выполняете это в SQL, чтобы иметь индекс для столбца Широта и Долгота. Мы пытались сделать это в SQL 2008 с пространственными индексами, но мы действительно не увидели ожидаемого повышения производительности. Хотя, если вы хотите вычислить в пределах определенного расстояния от ZIP, вам нужно подумать, собираетесь ли вы использовать ZIP-центроид или представление ZIP-кода в многоугольнике.

    Форум Haversine - хорошее место для начала.

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

    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
    

    Мы делаем это для 1200 мест. Я бы просто использовал формулу Хаверсайна на лету, хотя, в зависимости от вашего приложения, было бы лучше хранить ее на PHP, а не на SQL. (Наша реализация находится в .net, поэтому ваш учет может отличаться).

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

    В зависимости от выбранного вами маршрута, существуют способы ускорения вычислений числового расстояния путем просмотра долготы и широты и удаления тех, которые находятся за пределами предварительно определенного диапазона (например, если вы смотрите на все адреса в пределах 20 миль есть диапазон долготы, который вы можете рассчитать, все адреса которого должны находиться на расстоянии 20 миль.) Это может ускорить ваш запрос в случае необходимости.

    Мы на самом деле смотрели на хранение всех возможных комбинаций в нашей базе данных. В действительности это звучит так, как будто это может быть большое хранилище данных, но на самом деле это не так уж много. С индексами это может быть довольно быстро, и вам не нужно беспокоиться об оптимизации алгоритма и т. Д. Мы решили отказаться от него, потому что у нас было уравнение в C #, и это позволило нам кэшировать информацию, необходимую для выполнения всех вычислений в бизнес-уровень. Либо будет работать нормально, это просто вопрос ваших предпочтений.

    Лицензировано под: CC-BY-SA с атрибуция
    Не связан с StackOverflow
    scroll top