RT:這個景點周圍還有多少個其它的景點,這個酒店周圍還有多少可供選擇的酒店,這個餐館周圍是否有其它更舒適的吃房地方,那麼給定一個座標,怎麼定位離他最近的幾個目標了!
數據表:
存儲各個目標的座標值
- CREATE TABLE `map` (
- `id` INT( 10 ) NOT NULL ,
- `lat` DOUBLE NOT NULL ,
- `lng` DOUBLE NOT NULL
- ) ENGINE = MYISAM ;
依據各種業務不同,通常數據在一萬到幾十萬之間
解決辦法兩個:
方法一:SQL
直接上SQL:
求給定座標(37,121)附近(小於10公里)的景點
- SELECT id,lat,lng,
- ( 6371 * acos( cos( radians( 37 ) ) * cos( radians( lat ) )
- * cos( radians( lng ) - radians( 121 ) ) + sin( radians( 37 ) )
- * sin( radians( lat ) ) ) ) AS distance FROM map
- 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爲:
- select id,lat,lng from map where lat > 36.9 and
- lat < 37.1 and lng > 120.9 and lng < 121.1;
這樣一來查詢的結果通常之剩下幾十條,比之前動則幾百條的快了十倍
方法三:
方法一 + 方法二
sql:
- SELECT id,lat,lng,
- ( 6371 * acos( cos( radians( 37 ) ) * cos( radians( lat ) )
- * cos( radians( lng ) - radians( 121 ) ) + sin( radians( 37 ) )
- * sin( radians( lat ) ) ) ) AS distance FROM map
- where lat > 36.9 and lat < 37.1 and lng > 120.9 and lng < 121.1
- having distance<10 ORDER BY distance limit 0,30;
對於這種大數據量的計算,我們應該儘可能的縮小我們需要運算的範圍,將力量用在敵人最脆弱的地方!