給定地圖上一個座標,如何快速確定離這個座標最近的幾個點?

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;  

 

對於這種大數據量的計算,我們應該儘可能的縮小我們需要運算的範圍,將力量用在敵人最脆弱的地方!

 

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