给定地图上一个座标,如何快速确定离这个座标最近的几个点?

RT:这个景点周围还有多少个其它的景点,这个酒店周围还有多少可供选择的酒店,这个餐馆周围是否有其它更舒适的吃房地方,那么给定一个座标,怎么定位离他最近的几个目标了!

 

数据表:

存储各个目标的座标值

  1. CREATE TABLE `map` ( 
  2. `id` INT( 10 ) NOT NULL , 
  3. `lat` DOUBLE NOT NULL , 
  4. `lng` DOUBLE NOT NULL 
  5. ) ENGINE = MYISAM ; 

依据各种业务不同,通常数据在一万到几十万之间

 

解决办法两个:

方法一:SQL

直接上SQL:

求给定座标(37,121)附近(小于10公里)的景点

  1. SELECT   id,lat,lng,
  2. ( 6371 * acos( cos( radians( 37 ) ) * cos( radians( lat ) ) 
  3. * cos( radians( lng ) - radians( 121 ) ) + sin( radians( 37 ) )
  4.  * sin( radians( lat ) ) ) ) AS distance FROM map  
  5. having distance<10 ORDER BY distance  limit 0,30; 

这是最快的方法,测试数据量13W条,执行时间300ms左右,测试数据3W条,执行时间150ms左右。用不用你们自己觉得呢?

 

方法二:

方法一最大的问题就是速度慢,原因也很明显,对每个座标都要进行求距离的计算耗费了大量的空间和时间,sql解决不了就只能拿到脚本上面来完成了

曾间看到一哥们儿的做法是这么做的,假如现在是着朝阳区一个酒店附近的酒店,他就把所有的朝阳区酒店都拉出来,然后对他求距离运算,这么做也没错,但遇到极端情况,朝阳区下面少说也有千把个酒店,然后那个页面就爆慢。

通常情况下,我们提供附近的数据给用户,是提供可供他选择的数据,不能说你在北京三环找酒店,我推荐个河北的酒店给你,这显然就是不对的,通常人们可接受的范围10公里、30公里或者其它的范围内。那么根据这个我们就可以塞选很大一批数据。

经过测试,座标值相差0.1近视于10公里,什么意思了,就是座标(10,10) 与(10,10.1)的距离大概在10公里的样子,那么先把目标点集中在一块很小的区域内,这样以来性能就有很大的提升,sql为:

  1. select id,lat,lng from map where lat > 36.9 and 
  2. lat < 37.1 and lng > 120.9 and lng < 121.1; 

这样一来查询的结果通常之剩下几十条,比之前动则几百条的快了十倍

 

方法三:

方法一 + 方法二

sql:

  1. SELECT   id,lat,lng, 
  2. ( 6371 * acos( cos( radians( 37 ) ) * cos( radians( lat ) )  
  3. * cos( radians( lng ) - radians( 121 ) ) + sin( radians( 37 ) ) 
  4.  * sin( radians( lat ) ) ) ) AS distance FROM map   
  5. where lat > 36.9 and lat < 37.1 and lng > 120.9 and lng < 121.1 
  6. having distance<10 ORDER BY distance  limit 0,30;  

 

对于这种大数据量的计算,我们应该尽可能的缩小我们需要运算的范围,将力量用在敌人最脆弱的地方!

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章