在 Lindorm Ganos 中计算轨迹距离
针对轨迹距离计算场景,Lindorm Ganos 内置 ST_Length_Rows 函数来高效实现轨迹距离计算。利用原生时空二级索引和时空聚合计算下推,可以快速过滤不在范围内的数据、并行执行运算任务,有效解决上述问题。具体方法是:
- 利用主键索引快速根据车辆识别代码、时间戳对轨迹数据进行过滤。
- 利用时空二级索引对轨迹点进行范围过滤,剔除不在查询范围内的数据。
- 利用原生时空聚合计算,多 Region 并行计算轨迹点距离。Region 是分布式存储和负载的最小单元,表横向切割,根据 RowKey 分布于多个 Region 上。数据分布在多 Region 上,可以利用并行计算特性,加速运算。
使用限制: - 仅支持点类型(Point)列的聚合运算。
- 表中轨迹点的顺序需要用户通过主键进行保证,在车联网场景中,主键一般为车辆识别代码+时间戳。
- 如果过滤某个区域,仅计算区域内的点按顺序形成的轨迹距离。
- 当前 Lindorm GROUP BY 限制为 1000 个不同的 Key。
时空聚合函数 ST_Length_Rows 的具体文档请参考:聚合函数
示例
数据集
示例所用数据集为 T-Drive Taxi Trajectories,包含 2008 年北京一万多辆出租车一周的轨迹数据,包含 1500 万坐标点,轨迹总距离达 900 多万公里。下图展示的是车辆识别代码1-10的行驶轨迹:
数据示例如下:
taxi id
date time
longitude
latitude
1
2008-02-02 15:36:08
116.51172
39.92123
2
2008-02-02 15:56:08
116.47191
39.90718
3
2008-02-02 17:10:24
116.51627
39.91034
下载地址:https://www.microsoft.com/en-us/research/publication/t-drive-trajectory-data-sample/
我们建议在建表时预先设置 Region 数,以获得更好的聚合性能。建表语句如下:
CREATE TABLE tdrive(id INT, ts TIMESTAMP, p GEOMETRY(POINT), PRIMARY KEY(id,ts)) WITH (NUMREGIONS='4');
NUMREGIONS参数详细用法请参见:支持的 Table_Option 列表。
Lindorm 表结构如下,其中 id(车辆识别代码) 和 ts(时间戳) 为联合主键:
+--------------+------------+-------------+-------------+----------------+------------+
| TABLE_SCHEMA | TABLE_NAME | COLUMN_NAME | TYPE | IS_PRIMARY_KEY | SORT_ORDER |
+--------------+------------+-------------+-------------+----------------+------------+
| default | tdrive | id | INT | true | ASC |
| default | tdrive | ts | TIMESTAMP | true | ASC |
| default | tdrive | p | GEOMETRY(POINT) | false | none |
+--------------+------------+-------------+-----------------+------------+------------+
查询车辆轨迹并计算里程
• 根据 id 聚合轨迹并计算每个 id 的里程
SELECT id,ST_LENGTH_ROWS(p) FROM tdrive WHERE id<10 GROUP BY id;
+----+--------------------------+
| id | ST_LENGTH_ROWS(p) |
+----+--------------------------+
| 1 | 441415.1379062134844505 |
| 2 | 1672105.5085354075296573 |
| 3 | 1336898.1989478711426478 |
| 4 | 367018.3403825340860770 |
| 5 | 962951.4848773751934647 |
| 6 | 2695239.3950860189504903 |
| 7 | 840604.443770203001504 |
| 8 | 13.7600413799917481 |
| 9 | 1179411.02584998403695 |
+----+--------------------------+
返回的结果单位为米。
截取车辆轨迹并计算里程
• 按 id 和时间截取部分轨迹并计算距离
SELECT ST_LENGTH_ROWS(p) FROM tdrive WHERE id=1 AND ts<'2008-02-02 20:00:00';
+---------------------+
| ST_LENGTH_ROWS(p) |
+---------------------+
| 18135.1059201089410 |
+---------------------+
SELECT id,ST_LENGTH_ROWS(p) FROM tdrive WHERE id<3 AND ts<'2008-02-02 20:00:00' GROUP BY id ALLOW FILTERING;
+----+------------------------+
| id | ST_LENGTH_ROWS(p) |
+----+------------------------+
| 1 | 18135.1059201089410 |
| 2 | 97659.8754061263592983 |
+----+------------------------+
• 根据空间范围截取轨迹并计算里程
//代码效果参考:http://www.mwgw.cn/sitemap/post.xml
//代码效果参考:http://www.intpipe.com/sitemap/post.xml
//代码效果参考:http://www.ningluan.com/sitemap/post.xml
//代码效果参考:https://www.yopian.com/sitemap/post.xml
//代码效果参考:http://www.92demo.com/sitemap/post.xml注意,这种过滤方式必须先对点类型列建立时空二级索引:
CREATE INDEX p_idx ON tdrive(Z-ORDER(p));
对空间范围POLYGON((116.3902 39.9162, 116.4201 39.9162,116.4201 39.9007,116.3902 39.9007, 116.3902 39.9162))(上图粉色部分)内的点进行过滤并根据id聚合,计算里程的查询语句如下:
SELECT id,ST_LENGTH_ROWS(p) FROM tdrive WHERE id<11 AND ST_Contains(ST_GeomFromText('POLYGON((116.3902 39.9162, 116.4201 39.9162,116.4201 39.9007,116.3902 39.9007, 116.3902 39.9162))'),p) GROUP BY id;
+----+------------------------+
| id | ST_LENGTH_ROWS(p) |
+----+------------------------+
| 2 | 15968.158667253130873 |
| 10 | 20535.9638149385165832 |
| 5 | 7931.576244086410756 |
| 3 | 7387.28965893438078 |
| 6 | 1668.19998193752552 |
| 9 | 2474.95521518117699 |
| 7 | 1137.2432599704443 |
+----+------------------------+
性能
在不同数据量下,在 4 核 16 GB 4 节点宽表引擎集群中,使用查询语句 SELECT id, ST_Length_Rows(p) FROM tdrive WHERE id,查询时间分别为:
点数量
单 Region 计算耗时(ms)
4 Region 计算耗时(ms)
8 Region 计算耗时(ms)
25420
449
394
340
138227
1892
1852
1605
368092
4328
4615
4275
738396
7935
8696
7982
1468717
17062
16973
16239
总结
以轨迹处理分析场景为例,我们对 Lindorm Ganos 的轨迹截取、聚合距离计算进行了测试。从上面的测试过程来看,Lindorm Ganos 可以通过 SQL 语法便捷处理轨迹距离计算场景,同时使用主键索引、时空二级索引、多 Region 对计算进行加速,秒级响应可以满足车联网领域对轨迹距离计算的需求。