背景
緩沖區查詢是非常常見的空間查詢,用來查詢周邊的信息。本文介紹了H3來進行緩沖區查詢的方案。
H3簡介
H3是由Uber開源的一個六邊形分層索引網格系統,也是最近幾年實現數據聚合的主要趨勢,在H3出現之前大部分情況采用的是Geohash算法,墨卡托投影,還有一些其他投影技術,比如Google S2地理索引。
在不同緯度的地區使用等面積、等形狀的六邊形地理單元可以減少指標和特征歸一化的成本。另一方面,在常用的地理范圍查詢中,基於矩形的查詢方法,存在 8 鄰域到中心網格的距離不相等的問題,四邊形存在兩類長度不等的距離,而六邊形的周圍鄰居到中心網格的距離卻是有且僅有一個,從形狀上來說更加接近於圓形。
具體思路步驟
創建表按H3來分區,分區不超過一千個最好
CREATE TABLE pntsh3 ENGINE = MergeTree() PARTITION BY (geoh3) order by (geoh3,Lon,Lat) AS select id,geoToH3( toFloat64(Lon), toFloat64(Lat),3) geoh3,toFloat64(Lon) Lon, toFloat64(Lat) Lat from pnts
計算需要緩沖區范圍內幾個該級別下幾個格子可以覆蓋ceil(200000/h3EdgeLengthM(3)/2+1, 0)),得到H3集合。計算公式大概就是用距離處理六邊形兩邊和再加上一個一邊長,結果向上取整
select Lon, Lat,id from pntsh3 where geoh3 in (select arrayJoin(h3kRing(geoToH3(-120.419219,34.889755999999998, 3), toInt64(ceil(200000/h3EdgeLengthM(3)/2+1, 0))))) and greatCircleDistance(Lon,Lat,-120.419219,34.889755999999998) <=200000
select Lon, Lat,id from pntsh3 where geoh3 in (select arrayJoin(h3kRing(geoToH3(-120.419219,34.889755999999998, 3), toInt64(ceil(200/h3EdgeLengthM(3)/2+1, 0))))) and greatCircleDistance(Lon,Lat,-120.419219,34.889755999999998) <=200
相對於暴力計算,無論緩沖區大小均有一定提升
select Lon, Lat,id from pntsh3 where greatCircleDistance(Lon,Lat,-120.419219,34.889755999999998) <=200000
select Lon, Lat,id from pntsh3 where greatCircleDistance(Lon,Lat,-120.419219,34.889755999999998) <=200
通過H3索引的合理使用,有效減少了全表掃描,提升查詢速度
參考資料:
https://www.biaodianfu.com/uber-h3.html
https://github.com/uber/h3-js#module_h3.h3Distance
https://zhuanlan.zhihu.com/p/60861179