背景
车联网系统产生的时空轨迹数据中,包含车辆 id、时间戳、位置等信息。针对收集到的信息,需要统计出某辆车在一天之内的行驶距离,或是在节假日所有车辆行驶距离总和。具体例子如:
- 新能源汽车公司统计用户的年度行驶距离
- 网约车公司计算某个乘客打车的平均距离及总距离
- 网约车公司计算以某地为终点的平均打车距离
通过这些统计信息,业务可以基于这些信息进行进一步分析:
- 分析某市乘客日均出行距离,筛选日均通勤距离长的用户发放优惠券
- 以地铁站为终点,计算打车前往站点的平均距离,优化车辆分配
- 统计某地区私家车行驶强度,分析行驶距离对新能源汽车消费的影响
- 分析各省市汽车春运出行大数据报告
通常情况下,这些需求会使用如 Spark 这样的大数据平台解决,目前的通用解决方案是从数据库中提取时间范围内的点,再使用 Spark 等引擎进行轨迹距离计算。然而上述解决方案复杂,链路长:
- 效率过低:数据库内的轨迹点可能达亿级,从数据库提取点再传入 Spark 计算的数据传输可能非常耗时。
- 计算消耗大:如果数据没有排好序,需要 Spark 在内存中排序才能重构轨迹,然后计算距离。
上述问题在不使用时空引擎的情况下,整个链路计算耗时可能达几分钟,无法满足用户对海量数据实时查询的需求。
在 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 数,以获得更好的聚合性能。建表语句如下:
CREATETABLE 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<10GROUPBY 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=1AND ts<'2008-02-02 20:00:00';+---------------------+| ST_LENGTH_ROWS(p)|+---------------------+|18135.1059201089410|+---------------------+SELECT id,ST_LENGTH_ROWS(p)FROM tdrive WHERE id<3AND ts<'2008-02-02 20:00:00'GROUPBY id ALLOW FILTERING;+----+------------------------+| id | ST_LENGTH_ROWS(p)|+----+------------------------+|1|18135.1059201089410||2|97659.8754061263592983|+----+------------------------+
- 根据空间范围截取轨迹并计算里程
注意,这种过滤方式必须先对点类型列建立时空二级索引:
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<11AND 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)GROUPBY 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 对计算进行加速,秒级响应可以满足车联网领域对轨迹距离计算的需求。
Lindorm 多模数据库提供宽表、时序、搜索、文本、空间等多种数据模型,面向互联网、IoT、车联网等场景,是阿里巴巴核心业务提供关键支撑的数据库之一。
Lindorm Ganos 将 Ganos 对时空数据的处理能力深度融合到 Lindorm 中,提供原生的时空数据类型和时空算子,内置时空主键索引和时空二级索引,将时空算子下推并优化了查询计划,可以很好地满足车联网业务对轨迹、位置、范围等数据处理的需求,可以应用于车辆电子围栏报警、计算处理城市交通仿真模拟中的轨迹信息、轨迹距离聚合运算等场景。文章《轨迹数据处理“小钢炮”,Lindorm时空引擎Ganos实测》介绍了 Lindorm Ganos 在海量轨迹写入、检索、地理围栏实时报警场景下的能力优势。