Вариант 1:
Выполните расчет в базе данных, переключившись на базу данных, которая поддерживает GeoIP.
Вариант 2:
Выполните вычисления в базе данных: вы используете MySQL, поэтому следующая хранимая процедура должна помочь
CREATE FUNCTION distance (latA double, lonA double, latB double, LonB double)
RETURNS double DETERMINISTIC
BEGIN
SET @RlatA = radians(latA);
SET @RlonA = radians(lonA);
SET @RlatB = radians(latB);
SET @RlonB = radians(LonB);
SET @deltaLat = @RlatA - @RlatB;
SET @deltaLon = @RlonA - @RlonB;
SET @d = SIN(@deltaLat/2) * SIN(@deltaLat/2) +
COS(@RlatA) * COS(@RlatB) * SIN(@deltaLon/2)*SIN(@deltaLon/2);
RETURN 2 * ASIN(SQRT(@d)) * 6371.01;
END//
EDIT
Если в вашей базе данных есть индекс широты и долготы, вы можете уменьшить количество вычислений, которые необходимо рассчитать, разработав начальный ограничивающий прямоугольник в PHP ($ minLat, $ maxLat, $ minLong и $ maxLong) и ограничение строк подмножеством ваших записей на основе этого (ГДЕ широта между $ minLat и $ maxLat И долгота между $ minLong И $ maxLong). Тогда MySQL нужно только выполнить расчет расстояния для этого подмножества строк.
ДОПОЛНИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ (как пояснение к предыдущему редактированию)
Если вы просто используете оператор SQL, предоставленный Джонатоном (или хранимую процедуру для вычисления расстояния), тогда SQL все равно должен просмотреть каждую запись в вашей базе данных и рассчитать расстояние для каждой записи в вашей базе данных до того, как он может решить, возвращать ли эту строку или отбрасывать ее.
Поскольку вычисления выполняются относительно медленно, было бы лучше, если бы вы могли уменьшить набор строк, которые необходимо вычислить, исключив строки, которые явно выйдут за пределы требуемого расстояния, так что мы выполняем только дорогой расчет для меньшего количества рядов.
Если вы считаете, что в основном вы рисуете круг на карте с центром в начальной точке и с радиусом расстояния; тогда формула просто определяет, какие строки попадают в этот круг ... но все равно приходится проверять каждую строку.
Использование ограничивающей рамки похоже на то, чтобы сначала нарисовать квадрат на карте с левым, правым, верхним и нижним краями на соответствующем расстоянии от нашей центральной точки. Затем наш круг будет нарисован внутри этого прямоугольника, а самые северные, самые восточные, самые южные и самые западные точки на круге касаются границ прямоугольника. Некоторые строки будут выходить за рамки этого поля, поэтому SQL даже не пытается вычислить расстояние для этих строк. Он рассчитывает расстояние только для тех строк, которые попадают в ограничивающую рамку, чтобы увидеть, попадают ли они и в круг.
В PHP мы можем использовать очень простой расчет, который определяет минимальную и максимальную широту и долготу на основе нашего расстояния, а затем установить эти значения в предложении WHERE вашего оператора SQL. Это фактически наша коробка, и все, что выпадает за пределы этого, автоматически отбрасывается без необходимости фактически вычислять его расстояние.
На веб-сайте Movable Type есть хорошее объяснение этого (с кодом PHP), которое должно быть важным чтением для любого, кто планирует выполнять какую-либо работу с геопозицией в PHP.