ST_TrajectoryProfile算子
Lindorm Ganos 通过内置ST_TrajectoryProfile来高效的实现出入信息的统计。利用其原生实现的时空索引技术,可有效过滤掉大多数不在查询范围内的数据,减少扫描量、内存使用量,降低计算代价,从而可以有效解决上述的三个问题。具体的解决方法包括:
- 利用空间索引+过滤下推,减少扫描量,减少存储层与查询节点间的数据传输。降低数据库IO,减轻查询节点的内存、计算压力;
- 聚合加速:分组聚合计算并行进行,并将部分聚合逻辑下推到数据所在节点,减少查询节点内存和计算压力,提高聚合效率;
- 进出点计算封装:在聚合算子内部完成进出点的判断和轨迹段进出信息提取,减少业务层操作,使用方便
使用限制:由于在聚合操作前,1、2两步已经过滤掉了不在查询区域范围内的轨迹点,在进行出入点判断时,也就无法知道在查询范围以外的数据信息,因此对轨迹出入的判断有以下几个局限性:
1)划分轨迹段的条件依赖于时间阈值的设定,仅在轨迹点均匀采集点的情况下完全没有误差。对于中断采样情况,需要对返回结果进行额外的业务判断
2)对于出点,只能给出离开区域范围前的最后一个点,需要根据返回数据另外查询离开区域范围后的第一个点
使用示例
上述方案由Lindorm Ganos时空引擎的ST_TrajectoryProfile函数实现,函数具体说明详见ST_TrajectoryProfile
测试表结构
+-------------------+--------------+-------------------------------------+---------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME | TYPE | IS_PRIMARY_KEY | SORT_ORDER |
+-------------------+--------------+-------------------------------------+---------+----------------+------------+
| default | test | device_code | VARCHAR | true | ASC |
| default | test | collect_time | BIGINT | true | ASC |
| default | test | create_time | BIGINT | true | ASC |
| default | test | latitude | DOUBLE | false | none |
| default | test | longitude | DOUBLE | false | none |
| default | test | altitude | DOUBLE | false | none |
| default | test | gps_type | INT | false | none |
| default | test | gps_valid | INT | false | none |
| default | test | gps_status | INT | false | none |
| default | test | ... | ... | ... | ... |
+-------------------+--------------+-------------------------------------+---------+----------------+------------+
表的联合主键为device_code(车辆id)、collect_time(gps位置采集时间)、create_time(记录创建时间),另外还有其它74个非主键属性字段,包括对应collect_time的latitude(纬度)、longitude(经度)等。每辆车的gps按照10s的时间间隔连续采集轨迹点数据。
创建索引
为test表创建z-order二级索引,冗余longitude、latitude两列,避免主表回查
CREATE INDEX zorder_idx ON test (z-order(longitude, latitude)) INLCUDE(longitude, latitude);
进出点查询
要获取test表中的每个设备在指定时间段(2022-08-12 11:12:39 - 2022-08-17 09:39:19)内进出指定区域(以经纬度120.20495, 30.187485810为圆心,半径1000米内的区域)的情况,查询语句如下:
SELECT device_code, ST_TrajectoryProfile(longitude, latitude, collect_time, 10000) FROM test WHERE ST_DwithinSphere(ST_GeomFromText('POINT (120.20495 30.187485810)'), longitude, latitude, 1000.0) and collect_time >= 1660273959000 and collect_time <= 1660700359000 group by device_code;
ST_TrajectoryProfile函数返回各个轨迹段的概要信息(进出点和进出时间)。由于gps采样间隔为10s,ST_TrajectoryProfile的时间阈值参数为10000(ms)。
返回结果
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| device_code | ST_TRAJECTORYPROFILE(longitude, latitude) |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| 13184922496 | {"0":"{\"endY\":30.1830,\"endX\":120.2000,\"startY\":30.1820,\"startTime\":1660273959000,\"startX\":120.1989,\"endTime\":1660283962000}"} |
+-------------+-------------------------------------------------------------------------------------------------------------------------------------------+
该示例的返回结果表示在查询时间和区域内,只有一辆车进出了区域一次,进入时间为1660273959000 (2022-08-12 11:12:39),进入点为 (120.1989, 30.1820),离开前最后一次记录的时间为1660283962000 (2022-08-12 13:59:22),离开前最后一个记录点为 (120.2000, 30.1830)
注:该示例collect_time存储格式为LONG类型,可支持的时间字段类型还有TIMESTAMP、TIME
性能表现
测试环境
Lindorm Ganos测试集群:Lindorm 2.4.1版本,三节点16核32GB,1040G性能型云存储
测试数据
测试表结构与示例表结构相同,每条记录为车辆行驶过程中采集上传的一个轨迹点,表大小为3146MB,包含25辆车近3个月在经度范围[115.6253, 122.2817]、纬度范围[24.553466, 33.1788] 内的27045751个行驶轨迹点记录。
查询性能
• 查询的空间范围为半径1000m的圆形区域或面积在1平方千米左右的不规则区域,查询的时间范围均在一天左右。
• 返回时间主要取决于索引过滤后聚合计算的数据量和空间范围过滤条件的复杂程度。测试耗时均在20s以内,部分查询情况如下
查询条件
聚合计算数据量(查询范围内记录数)
查询耗时
//代码效果参考:https://www.xx-ph.com/sitemap/post.html
//代码效果参考:https://www.h3cw.com/sitemap/post.html
空间范围:(120.20495 30.187485810) 周边1000m,时间范围:2022-10-20 18:12:48 - 2022-10-21 18:12:48
3572683
17s
空间范围:矩形[(120.20322 30.18733),(120.21495 30.188485)],时间范围:2022-10-20 07:06:08 - 2022-10-21 15:26:08
23026
1s
空间范围:外包框为[(120.20122 30.186485),(120.21595 30.189483)] 的不规则多边形,时间范围:2022-10-01 08:27:16 - 2022-10-02 13:18:41
3008
6s