地理位置MySQL查询

Ben*_*ras 3 php mysql geolocation

我运行基于地理位置的社交网络。成员可以根据彼此的亲密程度来查看其他成员。

现在我的MySQL查询看起来像:

$lat_min = $geo['user_lat'] - 5;
$lat_max = $geo['user_lat'] + 5;
$long_min = $geo['user_long'] - 5;
$long_max = $geo['user_long'] + 5;    

$members_query = "SELECT " . $fields . " FROM members WHERE (user_lat BETWEEN " . $lat_min . " AND " . $lat_max . " AND user_long BETWEEN " . $long_min . " AND " . $long_max . ") OR (gc_lat BETWEEN " . $lat_min . " AND " . $lat_max . " AND gc_long BETWEEN " . $long_min . " AND " . $long_max . ")";
Run Code Online (Sandbox Code Playgroud)

user_lat并且user_long是基于地理位置的坐标(如果在浏览器中将其打开)。 gc_lat并且gc_long根据其IP地址进行协调。这些行均在数据库中建立索引。我将所有成员拉到10度以内。

问题是,对于我们的250,000多个成员,此查询大约需要2秒钟才能执行,我们希望网站能够扩展。

尝试2:我尝试为每个成员分配象限,例如“ 36x-99” ...我将经度和纬度四舍五入到最接近的3的倍数以标记象限,然后我仅将象限拉到象限的12度内成员所在的象限。

$members_query = "SELECT " . $fields . " FROM members WHERE quadrant IN ('36x-99', '33x-99', '30x-99', ...);
Run Code Online (Sandbox Code Playgroud)

这使我的查询速度没有明显差异。

有人对我应该做什么有任何想法?我需要找到一个解决方案,以使网站可以更好地扩展。

Jak*_*uld 5

问题是您在数据库中存储数据的方式不适合您正在执行的任务类型。PointGeometry数据点中使用值是必经之路。为此,实际上已经编码了4年多了,但是在找到它时遇到了问题。但是这篇文章似乎涵盖了所有内容。

编辑好的,找到了我的旧代码,但这是指我显然无法共享的旧客户端数据。但是,加快数据库中坐标的关键是使用POINT存储在数据库表中类型为的数据GEOMETRY有关更多详细信息,请参见官方MySQL网站。由于我需要重新访问这类代码及其概念的原因,有一段时间了,这里是一个快速的MySQL脚本,我用鞭策来创建一个带有示例数据的示例表,以传达基本概念。一旦了解了正在发生的事情,它就会为您带来很多不错的选择。

还发现了这个概念的伟大/简单的解释

并在MySQL 5.6中发现了另一个对空间数据的出色评估。有关索引和性能的大量信息。特别是关于MySQL空间索引的性能:

MyISAM表支持空间索引,因此上述查询将使用这些索引。

在另一方面:

InnoDB引擎不支持空间索引,那么这些查询将是缓慢的。

这是我的基本MySQL测试脚本,以帮助说明这一概念:

/* Create the database `spatial_test` */
CREATE DATABASE `spatial_test` CHARACTER SET utf8 COLLATE utf8_general_ci;

/* Create the table `locations` in `spatial_test` */
CREATE TABLE `spatial_test`.`locations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `coordinates` point NOT NULL,
  UNIQUE KEY `id` (`id`),
  SPATIAL KEY `idx_coordinates` (`coordinates`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

/* Insert some test data into it. */
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(27.174961 78.041822)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(27.985818 86.923596)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(44.427963 -110.588455)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(19.896766 -155.582782)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(40.748328 -73.985560)'));
INSERT INTO `spatial_test`.`locations` (`id`, `coordinates`) VALUES (NULL, GeomFromText('POINT(40.782710 -73.965310)'));

/* A sample SELECT query that extracts the 'latitude' & 'longitude' */
SELECT x(`spatial_test`.`locations`.`coordinates`) AS latitude, y(`spatial_test`.`locations`.`coordinates`) AS longitude FROM `spatial_test`.`locations`;

/* Another sample SELECT query calculates distance of all items in database based on GLength using another set of coordinates. */
SELECT GLength(LineStringFromWKB(LineString(GeomFromText(astext(PointFromWKB(`spatial_test`.`locations`.`coordinates`))), GeomFromText(astext(PointFromWKB(POINT(40.782710,-73.965310))))))) AS distance
FROM `spatial_test`.`locations`
;

/* Yet another sample SELECT query that selects items by using the Earth’s radius. The 'HAVING distance < 100' equates to a distance of less than 100 miles or kilometers based on what you set the query for. */
/* Earth’s diameter in kilometers: 6371 */
/* Earth’s diameter in miles: 3959 */
SELECT id, (3959 * acos(cos(radians(40.782710)) * cos(radians(x(`spatial_test`.`locations`.`coordinates`))) * cos(radians(y(`spatial_test`.`locations`.`coordinates`)) - radians(-73.965310)) + sin(radians(40.782710)) * sin(radians(x(`spatial_test`.`locations`.`coordinates`))))) AS distance 
FROM `spatial_test`.`locations`
HAVING distance < 100
ORDER BY id
;
Run Code Online (Sandbox Code Playgroud)

  • “我唯一想知道的是,它会计算绕地球的距离,还是穿过地球?” 很好的问题。这个问题似乎很好地解释了它。http://stackoverflow.com/questions/574691/mysql-great-circle-distance-haversine-formula (2认同)