深刻淺出空間索引:爲何須要空間索引

http://www.cnblogs.com/LBSer/p/3392491.html

1、問題html

  先思考個常見的問題:如何根據本身所在位置查詢來查詢附近50米的POI(point of interest,好比商家、景點等)呢(圖1a)?mysql

  每一個POI都有經緯度信息,我用圖1b的SQL語句在mySQL中創建了POI_spatial的表,其中lat和lng兩個字段來表明緯度和經度。爲後續分析方便起見,我人造了40萬個POI數據。sql

 2、傳統的解決思路數據庫

方法一:暴力方法函數

  該方法的思路很直接:計算位置與全部POI的距離,並保留距離小於50米的POI。spa

  插句題外話,計算經緯度之間的距離不能像求歐式距離那樣平方開根號,由於地球是個不規整的球體(圖2a),按最簡單的完美球體假設,兩點之間的距離函數應該如圖2b所示。rest

   該方法的複雜度爲:40萬*距離函數。咱們將球體距離函數寫爲mysql存儲過程distance,以後咱們執行查詢操做(圖3),發現花費了4.66秒。htm

該方法耗時的緣由顯而易見,執行了40萬次複雜的距離計算函數。blog

方法二:矩形過濾方法索引

  該方法分爲兩部:

  a)先用矩形框過濾(圖4a),判斷一個點在矩形框內很簡單,只要進行兩次判斷(LtMin<lat<LtMax; LnMin<lng<LnMax),落在矩形框內的POI個數爲n(n<<40萬);

  b)用球面距離公式計算位置與矩形框內n個POI的距離(圖4b),並保留距離小於50米的POI

  矩形過濾方法的複雜度爲:40萬*矩形過濾函數 + n*距離函數(n<<40萬)。

 

  根據這個思路咱們執行SQl查詢(圖5)(注: 經度或緯度每隔0.001度,距離相差約100米,由此推算出矩形左下角和右上角座標),發現過濾後正好剩下兩個POI。

  此查詢花費了0.36秒,相比於方法一查詢時間大大下降,可是對於一次查詢來講仍是很長。時間長的緣由在於遍歷了40萬次。

方法三:B樹對經度或緯度創建索引

  方法二耗時的緣由在於執行了遍歷操做,爲了避免進行遍歷,咱們天然想到了索引。咱們對緯度進行了B樹索引。

  此方法包括三個步驟:

  a)經過B樹快速找到某緯度範圍的POI(圖6a),個數爲m(m<40萬),複雜度爲Log(40萬)*過濾函數;

  b)在步驟a過濾獲得的m個POI中查找某經度範圍的POI(圖6b),個數爲n(n<m),複雜度爲m*過濾函數;

  c) 用球面距離公式計算位置與步驟b獲得的n個POI的距離(圖6c),並保留距離小於50米的POI

 

  執行SQL查詢(圖7),發現時間已經大大下降,從方法2的0.36秒降低到0.01秒。

3、B樹能索引空間數據嗎?

  這時候有人會說了:「方法三效果如此好,可以知足咱們附近POI查詢問題啊,看來B樹用來索引空間數據也是能夠的嘛!」

  那麼B樹真的可以索引空間數據嗎?

1)只能對經度或緯度索引(一維索引),與指望的不符

  咱們期待的是快速找出落在某一空間範圍的POI(如矩形)(圖8a),而不是快速找出落在某緯度或經度範圍的POI(圖8b),想象一下,我要查詢北京某區的POI,可是B樹索引不只給我找出了北京的,還有與北京同一維度的天津、大同、甚至國外城市的POI,當數據量很大時,效率很低。

2)當數據是多維,好比三維(x,y,z),B樹怎麼索引?

  好比z多是高程值,也多是時間。有人會說B樹其實能夠對多個字段進行索引,但這時須要指定優先級,造成一個組合字段,而空間數據在各個維度方向上不存在優先級,咱們不能說緯度比經度更重要,也不能說緯度比高程更重要。

3)當空間數據不是點,而是線(道路、地鐵、河流等),面(行政區邊界、建築物等),B樹怎麼索引?

  對於面來講,它由一系列首尾相連的經緯度座標點組成,一個面可能有成百上千個座標,這時數據庫怎麼存儲,B樹怎麼索引,這些都是問題。

 

  既然傳統的索引不能很好的索引空間數據,咱們天然須要一種方法能對空間數據進行索引,即空間索引。

下節將對空間索引分類體系、原理、優缺點及數據庫支持狀況進行闡述(正在寫)。

相關文章
相關標籤/搜索