WebGIS中GeoHash編碼的研究和擴展

文章版權由做者李曉暉和博客園共有,若轉載請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/html

1.背景

1.1普通地理編碼流程

將採集的POI入庫後,數據庫裏保存有該POI的位置描述、X、Y等信息。當須要進行逆編碼查詢時,前端傳入座標的X、Y值,後臺構建查詢範圍查詢,而且對查詢出來的值進行距離排序。前端

1.2普通地理編碼的幾點劣勢

a.前端查詢url中的X、Y值爲真實值,可能會暴露相關真實信息。算法

b.前端查詢的url由於X、Y值的長度而變得比較長。數據庫

c.後臺中,須要同時對X列、Y列作查詢判斷。緩存

d.由於傳入的X、Y值總在變化,數據庫中的查詢很難進行緩存優化。微信

e.數據庫中保存的是真實X、Y數據,增長了存儲空間。網絡

2 GeoHash算法簡介

2.1算法背景

Geohash的初衷是如何用盡可能短的URL來標誌地圖上的某個位置,而地圖上的位置通常是用經緯度來表示,問題就轉化爲如何把經緯度轉化爲一個儘可能短的URL。性能

2.2GeoHash算法的描述

具體來講GeoHash算法的主要思想是對某一數字經過二分法進行無限逼近。這裏以經緯度區間(經度(-180,180),緯度(-90,90))爲例子來進行講解。測試

2.2.1 哈夫曼編碼

假設緯度值爲48,精確到1度便可,則其編碼流程以下所示:優化

 

 

                       

以左向爲0,右向爲1,最後48精確到1度的編碼爲:11000010。

對經度一樣能夠作該編碼逼近。

2.2.2編碼融合

對經緯度分別作了編碼後,須要將兩個編碼進行融合。融合規則爲:將經度和緯度的編碼合併,奇數位是緯度,偶數位是經度。

好比:緯度39.92324精確到0.001後的編碼爲1011 1000 1100 0111 1001。經度116.3906精確到0.001後的編碼爲1101 0010 1100 0100 0100。二者融合後的編碼爲:11100 11101 00100 01111 00000 01101 01011 00001。

2.2.3 編碼字符串化

這裏使用Base32算法對編碼進行字符串 化,Base32的規則以下:

 

咱們將39.92324, 116.3906(11100 11101 00100 01111 00000 01101 01011 00001)進行Base32的字符串化後得到字符串:wx4g0ec1。

3.基於GeoHash算法的擴展

3.1互聯網GeoHash算法的侷限

互聯網GeoHash算法主要針對的是經緯度系統,因此其算法中的編碼範圍、編碼精確度都相對固定。

範圍爲[-90,90],[-180,180]。

 

在緯度相等的狀況下:

經度每隔0.00001度,距離相差約1米;

每隔0.0001度,距離相差約10米;

每隔0.001度,距離相差約100米;

每隔0.01度,距離相差約1000米;

每隔0.1度,距離相差約10000米。

 

在經度相等的狀況下:

緯度每隔0.00001度,距離相差約1.1米;

每隔0.0001度,距離相差約11米;

每隔0.001度,距離相差約111米;

每隔0.01度,距離相差約1113米;

每隔0.1度,距離相差約11132米。

Geohash,若是geohash的位數是6位數的時候,大概爲附近1公里。

可是假如須要編碼的座標爲平面座標時,以上算法必須進行相關修改才能使用。

3.2GeoHash算法擴展

3.2.1 根據所需精確度獲取編碼長度

這裏以平面座標系爲例子。平面座標的單位是M,若是想要編碼的精確度精確到1M,則須要算出此時須要保留的編碼長度應該是多少。具體算法與哈夫曼編碼的思路基本相同,如下是代碼截取:

 

這裏,須要知道編碼範圍、編碼精確位數。由於5位數的編碼等於一個Base32字符串,因此最後返回的值除以5。

固然,這裏是經緯度座標系也能夠,只要規定好範圍以及編碼精確位數便可。

3.2.2 編碼算法優化

編碼時,編碼範圍再也不是固定的經緯度範圍,而是根據傳遞進來的範圍值來進行編碼。具體代碼以下:

 

4.性能測試

4.1數據準備

這裏我準備了13萬條數據(測試數據中大量重複數據):

 

 

數據爲平面座標系數據,對全部數據已經進行了GeoHash編碼,爲了方便測試,這裏一樣存入了X、Y座標。

 

4.2 普通編碼查詢 VS GeoHash編碼查詢

測試座標點爲:505214.06,305104.09。對其進行精確到100M的GeoHash編碼,編碼值爲:kx5。

4.2.1範圍查詢命中率

4.2.1.1普通查詢命中率

查詢中爲了去掉重複項,因此稍顯繁瑣。

查詢範圍爲(CoordinateX < 505314.06 and CoordinateX > 505114.06 and CoordinateY < 305204.09 and CoordinateY >305004.09)具體以下,共查詢到:12項。

 

4.2.1.2 GeoHash查詢命中率

由於編碼已經精確到100M了,因此直接等於該編碼便可,查詢獲得的結果爲6項。

 

4.2.1.3 對比分析

對比兩種查詢,很明顯GeoHash編碼查詢法查詢到的數據要少一些。仔細分析可見:在傳統查詢中,距離在50M之內的前6項,均出如今了GeoHash查詢中。可是其餘6項則沒有。

咱們能夠推斷爲,雖然編碼精度設置的爲100M,可是最後一位的編碼應該具體是精確到了100/2=50M 的範圍。

因此,咱們能夠推斷:GeoHash是能大體查詢出要求範圍的數據的,精確度比較高,可是查詢所得數據量比真實的範圍查詢要少。

4.2.2 查詢效率

4.2.2.1普通查詢

清除查詢緩存後,進行範圍查詢,須要0.281S。

 

在X、Y上分別創建索引後,須要0.172S。

 

4.2.2.2 GeoHash查詢

不創建索引,須要耗時0.499S。

 

創建索引後,耗時0.156S。

 

第二次命中時,耗時:0.031S。

 

 

4.2.2.3查詢性能對比分析

 

 

4.2.2.3.1查詢時間

不考慮網絡環境、查詢時電腦自己CPU等性能偶然影響,單純測試結果以下:

查詢類型

(數據量13W)

無索引查詢時間

有索引查詢時間

二次命中時間

普通地理編碼查詢

0.281S

跟索引創建方式有關係,單純在XY上創建索引,時間反而更久,須要:0.172S

0.094S

GeoHash編碼查詢

0.499S

0.156S

0.031S

 

可見GeoHash由於是字符串查詢,其自己是比較耗時的。可是當作了索引後,其查詢速度是快於普通查詢的,並且其二次命中時查詢速度比普通查詢二次命中會更快。其緣由比較簡單:單列索引、單列命中顯然是高於多列的。

4.2.3.2 資源消耗分析

普通查詢的資源消耗信息:

 

 

GeoHash查詢的資源消耗信息:

 

其中:

cardinality是指計劃中這一步所處理的行數。

cost指cbo中這一步所耗費的資源,這個值是相對值,和cpu_cost、io_cost是有關係的。

cost是由其餘幾個因素共同決定的,這裏暫時不進行深刻的研究。通常狀況下,在一張表只有一條記錄的狀況下,cpu_cost會有個初始值(常見的是2萬多或3萬多),隨着記錄的增長,cpu_cost也成比例的增長。對於io_cost來講,若是訪問的記錄在一個db_block中,值是不變的。

bytes指cbo中這一步所處理全部記錄的字節數,是估算出來的一組值。

對比性能分析表可見:

GeoHash表中的cardinality和bytes是明顯低於普通查詢的,究其緣由也仍是由於其只需查詢一列便可。

5.總結

GeoHash算法的幾個特色:

a.GeoHash編碼後,得到的位置信息爲範圍信息,而非真實的座標精確值。

b.GeoHash編碼後,將X、Y座標融合成一個值,數據庫存在中既能夠減小存儲空間,也便於優化查詢。尤爲是編碼後,必定範圍內的點均是一樣編碼,興趣點查詢的二次命中率會大大提升,進一步加快查詢速度。

c.GeoHash的編碼能夠容易的表示出範圍包含關係,這樣很是便於進行範圍查詢。

d.查詢時前端URL長度變短。

6.三個問題

6.1如何查詢最近點

GeoHash查詢出來的僅僅是某個範圍內的數據,須要對返回的數據在進行距離運算,排序後最近的即是。其優化效率主要體如今範圍查詢上。

6.2查詢效率能優化多少?

測試在1W條數據如下時不明顯。

10W條附近時,開始有0.1S間的小差距。

類推,當數據量越大時,效果越明顯。

6.3兩個點離的越近,geohash的結果相同的位數越多,對麼?

這一點是有些用戶對geohash的誤解,雖然geo確實儘量的將位置相近的點hash到了一塊兒,但是這並非嚴格意義上的(實際上也並不可能,由於畢竟多一維座標),例如在方格4的左下部分的點和大方格1的右下部分的點離的很近,但是它們的geohash值必定是相差的至關遠,由於頭一次的分塊就相差太大了,不少時候我 們對geohash的值進行簡單的排序比較,結果貌似真的可以找出相近的點,而且彷佛仍是按照距離的遠近排列的,但是實際上會有一些點被漏掉了。
上述這個問題,能夠經過搜索一個格子,周圍八個格子的數據,統一獲取後再進行過濾。這樣就在編碼層次解決了這個問題。
    既然不能作到將相近的點hash值也相近,那麼geohash的意義何在呢?
    我的覺以爲geohash仍是至關有用的一個算法,畢竟這個算法經過無窮的細分,能確保將每個小塊的geohash值確保在必定的範圍以內,這樣就爲靈活的周邊查找和範圍查找提供了可能。

7.最後提一個有趣的問題——倫敦到紐約的距離怎麼算

 

這個問題是前幾天一個讀博士的朋友問的我,思考這個問題挺有趣的。其中會涉及到長距離和短距離問題,推薦一篇相似博客:咱們看到的地圖一直都錯得離譜(http://blog.sina.com.cn/s/blog_517eed9f0102w4rm.html);

 

 

                                                                           -----歡迎轉載,但保留版權,請於明顯處標明出處:http://www.cnblogs.com/naaoveGIS/

                                                                           若是您以爲本文確實幫助了您,能夠微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^

                                      

相關文章
相關標籤/搜索