选项1: 通过切换到支持GeoIP的数据库来对数据库进行计算。
选项2: 请在这样的databaseusing存储过程中的计算:
CREATE FUNCTION calcDistance (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//
如果您对您的数据库中的纬度和经度索引,可以减少需要计算的次数通过在PHP中创建初始边界框($ minLat,$ maxLat,$ minLong和$ maxLong)并将行限制为您的条目子集(WHERE latitude BETWEEN $ minLat AND $ maxLat和经度BETWEEN $ minLong AND $ maxLong)。那么MySQL只需要执行该行子集的距离计算。
如果您只是使用存储过程来计算距离),那么SQL仍然需要查看数据库中的每条记录,并计算数据库中每条记录的距离,然后才能决定是否返回排或放弃它。
因为计算执行起来相对较慢,所以如果您可以减少需要计算的行集合,消除显然会超出所需距离的行,那么我们只会执行对于较少数量的行来说,这是昂贵的计算。
如果你认为你正在做的事情基本上是在地图上画一个圆,以你的初始点为中心,并且有一个距离半径;那么该公式只需确定哪些行位于该圆圈内......但它仍然需要检查每一行。
使用边界框就像在地图上首先绘制一个正方形,左边,右边,顶部和底部边距离我们中心点的适当距离。然后我们的圈子将被绘制在该框内,圆圈上最北端,最东端,最南端和最西端的点与框的边界接触。有些行将落在该框之外,所以SQL甚至不打算计算这些行的距离。它仅计算落在边界框内的那些行的距离,以查看它们是否落入圆内。
在你的PHP中(猜测你正在从$变量名运行PHP),我们可以使用一个非常简单的计算,根据我们的距离计算最小和最大经度和纬度,然后将这些值设置为WHERE你的SQL语句的子句。这实际上就是我们的盒子,任何超出此范围的东西都会自动丢弃,而无需实际计算其距离。
对于任何计划在PHP中执行任何GeoPositioning工作的人来说,这应该是必不可少的解释(使用PHP代码)。
EDIT calcDistance存储过程中的值6371.01是以乘数表示的返回结果,以千米为单位。如果你想造成,海里,米,使用适当的替代乘数无论
随着_”支持GeoIP'_数据库,你实际上意味着_'with空间或地理编码indexes'_(例如PostGIS的等)?我没有看到'IP'的点'有关问题GeoIP';) – Wrikken 2010-10-21 11:10:20
@Wrikken PostGIS的是在我的脑海里的数据库,当我输入的IP被输入了“支持的GeoIP数据库” ...没有想到,因为我一直在玩IP阅读经纬度,并且最近用它作为距离计算的基准位置。 –
2010-10-21 11:16:10