随着定位技术的不断发展,导致大量的时空数据产生,例如 GPS 设备、手机等,这些设备会定时记录使用者的地理位置。
目前各类成熟的数据库大多已支持空间类型和空间索引,比如 Postgresql(关系型)、ElasticSearch(文档型)、Redis(内存型)等,或者一些 KV 数据库比如 HBase,其自身不支持,但 GeoMesa 插件让它支持了空间能力,而在时序数据库领域,空间类型和空间索引支持还有限。
概念
以车载GPS设备为例,一个gps设备每10秒上报经纬度、时间、速度、方向等数据,如下:
车牌号 | 经度 | 纬度 | 时间 | 速度 | 方向 |
---|---|---|---|---|---|
浙 A11111 | 121.148 | 30.048 | 2023-06-05 10:00:00 | 60 | 1 |
浙 A22222 | 121.148 | 30.048 | 2023-06-05 10:00:00 | 60 | 1 |
浙 A33333 | 121.103 | 30.025 | 2023-06-05 10:00:00 | 80 | 0 |
浙 A11111 | 121.148 | 30.048 | 2023-06-05 10:00:10 | 60 | 1 |
浙 A22222 | 121.148 | 30.048 | 2023-06-05 10:00:10 | 60 | 1 |
浙 A33333 | 121.103 | 30.025 | 2023-06-05 10:00:10 | 80 | 0 |
…… | …… | …… | …… | …… | …… |
大多数据库主要基于 B+树作为索引,可以很好地支持单维数值范围查询,但对于时空数据,要支持的场景更复杂,比如
1、查询某一个区域一段时间内进过的车
2、查询某一个区域的车辆数
3、查询与某辆车同行的车
这些查询往往需要使用到时空范围查询,即二维空间范围加一维时间范围,时空索引是为了加快时空查询效率而设置的数据结构,它在空间索引之上增加了时间维度,故下面先介绍空间索引技术,然后再来介绍时空索引。
空间索引
先来思考一个问题,数据库的B+树方案已经很成熟了,那能否借助它直接实现高效的空间范围查询呢?这里有2个方案
1、只对经度或纬度索引(一维索引)
这种方案虽然起到了索引效果,但效果可能不够好,想象一下,若只对经度建立索引,要查询某个路口经过的车,B+树索引不仅给我找出了该路口的,还有与该路口同一维度路口的车,当数据量很大时,效率就低了。
2、对经纬度建立联合索引
B+树是可以对多个字段进行索引,比如 PG 中支持联合索引,但这时需要指定优先级,形成一个组合字段,而空间数据在各个维度方向上不存在优先级,只能随机定一个。
以上两种方案,都是会影响到索引的准确度,最终影响查询效率,另外在扩展性上,假如当空间数据不是点,而是线(道路、地铁、河流等),面(行政区边界、建筑物等),B+树就没法支持了。
所以基于性能和扩展性,我们会发现研究空间索引是有必要,常见的空间索引按不同的思想,大致以下三类:
图1 空间索引分类
针对这些索引的原理,进行优缺点和适用场景的总结,如下
方法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
网格索引 | 实现简单 | 1、存储空间浪费 2、无法有效的切分网格,不易于用工程实现 | 空间数据比较均匀的场景,快速构建原型 |
四叉树 | 实现简单 | 存储空间浪费 | 空间数据比较均匀的场景,快速构建原型 |
R 树 | 1、索引准确度高 | 1、实现复杂 2、写入过程会有较多的分裂和平衡 | 读多写少的场景,适合离线的路网、行政区等空间对象索引 |
空间填充曲线 | 1、不需要做分裂、平衡等操作 2、实现简单 | 1、索引准确度上稍弱 | 写多读少的大规模场景,如大规模GPS数据 |
哈希思想
哈希是通过一个哈希函数将关键字映射到内存或外存的数据结构,可以想象成 Java中HashMap的数据结构。
网格索引
网格索引是对地理空间进行网格划分,划分成大小相同的网格,每个网格对应着一块存储空间,存储空间存储该网格对应的空间对象。
举个例子,我们将地理空间进行网格划分,并进行编号。该空间范围内有三个空间对象,分别是 id=5 的街道,23 的河流和 11 的商圈。这时候我们可以按照哈希的数据结构存储,每个网格对应着一个存储桶,而桶里放着空间对象,比如对 2 号网格,里面存储着 id=5 的空间对象,对 35 号网格,桶里放着 id=5 和 id=23 的空间对象。
图2 网格索引结构
假如我们要查询某一空间范围内有哪些空间对象,比如下面的红框就表示空间范围,我们可以很快根据红框的空间范围算出它与 35 号和 36 号网格相交,然后分别到 35 号和 36 号网格中查找空间对象,最终找出 id=5 和 id=23 的空间对象。
图3 网格索引查询示意图
树思想
树是通过将关键字按树状组织起来,在数据库中主流的为 B+树,一维上的关键字比较操作主要是大于,小于,等于,空间上的关键字拓展成包含关系。
四叉树
Quad-Tree 的最初设计源自论文《Quad Trees: A Data Structure for Retrieval on Composite Keys》。Quad-Tree 在二维上将空间分为四组相同的子象限,且只有每个叶节点中会包含有关时空数据。Quad-Tree 里的每个节点要么正好有 4 个子节点,要么就是没有子节点(为一个树叶节点)。如图 4 所示,是一种典型的 Quad-Tree。同样地,Quad-Tree 也可以表示为树状结构,如图 5 所示,从某种意义上来说,四叉树是有层次结构的网格索引。
图4 四叉树
图5 四叉树树形结构
R 树
R-Tree 是一种平衡树,它只在叶节点中存放指向数据的指针,由 Guttman 在 1984 年 SIGMOD 中提出[1]。Guttman 首先提出了 MBR 的概念,即最小边界矩形 Minimum Bounding Box,如图 1 所示,其用一个边平行于坐标轴的最小的矩形框住空间对象。在查询时,只需要先找到空间对象的 MBR 即可。找 MBR 的任务相对于直接寻找空间对象本身来说容易了很多。
图6 MBR示意图
R-tree 吸纳了 B+tree 的思想,对数据进行分割。多个相邻的 MBR,可以被包含在一个更大的 MBR 中,如图 2 中 R6、R9 以及 R10 三个矩形,可以被包含在 R3 中,而 R11 与 R12 则被包含在 R4 中。因此,可以用一个更大的 MBR 框住内层的小 MBR。继续迭代,总能找到若干个最大的区域,如图 2 所示。一层一层构建 MBR 的操作,非常类似 B+tree 的构建,最终以一种类树状的形式,将所有的时空对象给容纳进去,如图 3 所示。查询时,通过先找外层的 MBR,再不断遍历相交的子层,我们便可以很快找到内层 MBR 的大概位置。
图7 R树树形结构
降维思想
降维是将二维或者更多维数据降成一维,再用一维的方式进行索引。
空间填充曲线
空间填充曲线是通过空间填充曲线将空间数据降为一维数据,再用一维的方式进行索引,如 B+树。空间填充曲线保证在空间上相邻的点在一维数据上也尽可能相邻。
空间填充曲线包含两种技术,1、空间填充曲线,2、空间编码。常见空间填充曲线有 z-ordering、Hilbert 等,编码方式上有 geohash、z2、S2等。下面以ES采用的 z-ordering空间填充曲线 和 geohash空间编码进行说明:
1、z-ordering
Z-排序(Z-ordering)技术将数据空间循环分解到更小的子空间(被称为 Peano Cell),每个子空间根据分解步骤依次得到一组数字,称为该子空间的 Z-排序值。子空间有不同的大小,Z-排序有不同的长度,显然,子空间越大,相应的 Z-排序值越短。这里,分辨率(resolution)是指最大的分解层次,它决定了 Z-排序值的最大长度。
图8 z-ordering示意图
以经纬度值:(116.389550, 39.928167)进行算法说明,对纬度 39.928167 进行逼近编码 (地球纬度区间是[-90,90])
1、区间[-90,90]进行二分为[-90,0),[0,90],称为左右区间,可以确定 39.928167 属于右区间[0,90],给标记为 1
2、接着将区间[0,90]进行二分为 [0,45),[45,90],可以确定 39.928167 属于左区间 [0,45),给标记为 0
3、递归上述过程 39.928167 总是属于某个区间[a,b]。随着每次迭代区间[a,b]总在缩小,并越来越逼近 39.928167
4、如果给定的纬度 x(39.928167)属于左区间,则记录 0,如果属于右区间则记录 1,序列的长度跟给定的区间划分次数有关,如下图;
图9 纬度划分示意图
同理,地球经度区间是[-180,180],可以对经度 116.389550 进行编码。通过上述计算,纬度产生的编码为 1 1 0 1 0 0 1 0 1 1 0 0 0 1 0,经度产生的编码为 1 0 1 1 1 0 0 0 1 1 0 0 0 1 1。
图10 经纬度z-ordering编码
2、Geohash
将 11100 11101 00100 01111 0000 01101 转成十进制,对应着 28、29、4、15,0,13 十进制对应的 base32 编码就是 wx4g0e,如下
图11 geohash对照表
这个 wx4g0e 就是一个 geohash 值,GeoHash 表示的并不是一个点,而是一个矩形区域。GeoHash 编码的前缀可以表示更大的区域。例如 wx4g0ec1,它的前缀 wx4g0e 表示包含编码 wx4g0ec1 在内的更大范围。
时空索引
时空索引是在空间索引的基础上增加时间维度,理论上有3种实现方式。
1、先将时间分片,在每个时间分片内构建空间索引,比如 ES 的 shard 按时间来分,如 1 周 1 个 shard,空间索引使用空间填充曲线;PostGis按时间分区表,空间索引使用 R 树。
2、先空间网格化,每个网格构建时间索引,这种方式与第一种相似,但在实际工程中很少使用,可能在于在大多数场景下时间相较于空间更容易被接受作为分片,而且数据库按时间删除数据也是一种基础功能,相较于第一种方式,这种方式在实现该功能上会复杂一些。
3、时间作为新的维度加入空间中来,这个在 GeoMesa 的 Z3 索引有实现,在原有(x,y)的基础增加了t,用空间填充曲线将3维编码成1维,这种方式不大适合工程化,因为有较大的弊端,在时空查询条件的时空尺寸不匹配的情况下,空间会有严重的放大问题,有兴趣可以看京东 just 在 2020 ICDE 发表的这篇 JD Urban Spatio-Temporal Data Engine 这篇论文。
综上,在时空索引上采用第一种方式普遍来说是最适合的,而对于在大数据轨迹实时更新场景下,比较适合用空间填充曲线的方式,因为对R树等多维方案而言,它们在读取上有优势,但不适合频繁写入场景,因为涉及分裂、平衡等 IO 操作。不过从狭义索引的角度来看,第一种方式已经不是严格意义上索引了,狭义的索引即索引为一种数据结构,这种方式更多的是将时间分区与空间索引结合起来。
可能有人会有这个疑问,用了空间填充曲线,转换为 1 维后,采用的一般也是 B+树,但 B+树也会不停做分裂和平衡,仍然不适合高吞吐的写入场景,这个其实跟所采取的存储引擎有关,若采用关系型数据库的B+树存储引擎,是会存在这个情况,但现在很多Nosql,大多采用LSM存储引擎,以HBase为例,采用LSM的存储引擎,HFile的数据索引为B+树索引,在写缓存(内存)中已经对 rowKey(索引关键字)进行了排序,这样除了Merge时做一下树的重组织,其它时候都不需要。
实现方案
前面介绍了空间索引、时空索引技术,再回归到我们的时序数据库中,以 Influxdb、Tdengine 和 IOTDB 这 3 个业界主流的时序数据库为例。
主要面向场景 | 数据库 | GeoMetry 数据类型 | 时空索引 | 方案 |
---|---|---|---|---|
工业互联网 | IOTDB | 不支持 | 不支持 | / |
DevOpt 监控 | Influxdb | 支持(实验功能) | 支持(实验功能) | 将空间数据通过 google S2 编码后作为 tag 的一部分,存在时间线爆炸的问题,不适合大量移动类的传感器设备 |
物联网 | TDengine | 支持 | 不支持 | / |
可以看到还没有较好的时空索引技术应用在上述时序数据库上,推测下原因,可能主要还是面临的场景决定,对于 IOTDB 而言,其面向工业互联网垂直场景,观测的设备是不可移动的,自然也就不存在时空查询的需求;对于 Influxdb 而言,其面向 DevOpt 监控场景,关注某应用服务的 cpu、mem、io 等指标,至于应用服务所在的服务器位置并不重要,当前 influxdb 也在尝试进入更广阔的的物联网领域,所以实现了时空索引,但它采用的方案是妥协性的方案,把空间进行编码后作为标签 tag 的一部分,不涉及数据库内核的修改,不适合大规模移动设备下的场景。TDengine 虽然还不支持时空索引,但在最新版本已支持空间数据的存储,同时它面向物联网领域,估计不久后在内核层面会支持时空索引。
要在时序数据库中实现时空索引,需要考虑到现有工程的约束和特点,这里我们提出一种可能的解决方案,现有时序数据库通常支持标签索引,比如 Influxdb、Tdengine 对标签和对象 ID 构建倒排索引,IOTDB 的区别在于将倒排索引改成了层级树索引,但流程上都是先通过倒排索引或者层级树索引找到 ID,再根据 ID 从时序文件或者缓存中获取数据。同样地我们可以在不改变基本流程的思路上,增加时空索引,具体如下:
1、在时序数据库内部新增时空索引,时空索引的 Key 为时空块,Value 为 ID 的集合,其中 Key 的空间块可由空间填充曲线编码得到。
2、通过 ID 链接到时序文件,时序模型可基本不变,只在原有 ID 块的头部增加 MBR 和轨迹签名用来做一些快速过滤。
图12 时序数据库支持时空索引设计示意图
小结
时空索引可提升时空查询效率,本文先对时空索引的概念进行介绍、之后对空间索引、时空索引技术进行分析,最后结合时序数据库设计的核心特点以及时空索引技术,提出一种实现方案思路供参考。
参考文献
1、网格索引: :https://www.cnblogs.com/mumu122GIS/p/10615979.html
2、R 树,四叉树:HBsae与时空索引技术杂谈 - 墨天轮
更多内容,敬请关注同名微信公众号:时空大数据兴趣小组。