轨迹数据处理“小钢炮”,Lindorm时空引擎Ganos实测

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 MongoDB,独享型 2核8GB
推荐场景:
构建全方位客户视图
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 本文在Lindorm Ganos中对常用的时空场景进行测试,用过程和实际数据展示Lindorm Ganos具备的能力和特性

引言


车联网、共享出行、智慧物流等领域的快速发展产生了大量的时空轨迹数据。这些轨迹数据源源不断的产生,要求存储系统具备较高的写入能力、可扩展能力以及较低的存储成本。同时针对这些轨迹数据又产生了各类时空查询,按照实时性的要求分为三类场景:


  • 在线查询,如针对历史轨迹的时空范围查询(过去24小时车辆在某个区域的行驶轨迹)、周边查询(附近2公里内的出租车)等,一般要求在毫秒或秒级。
  • 实时计算,如实时的电子围栏判断(判断车辆是否驶出目标范围),时空统计(实时热力图,计算某个区域实时车辆数),一般要求在毫秒级。
  • 离线计算,针对大规模历史轨迹数据做挖掘,比如根据轨迹挖掘出迁徙模式。


一直以来,各类NoSQL数据库对时空数据的高并发写入、在线查询等支持并不完善,每个NoSQL数据库基本上只能用于某种特定场景。比如:基于Hadoop平台的方案一般会在UDF层提供时空算子,但缺少时空索引,无法将时空算子下推到存储层,基本上只能用作离线查询;Apache Sedona(原GeoSpark)内置了时空索引,但一般用于时空数据挖掘等场景,不适合实时在线查询;MongoDB内置了2dsphere空间索引,但由于写入速度、扩展性的瓶颈,普遍只将其用作LBS等场景;GeoMesa作为一款中间件,可以借助HBase等存储具备较高的写入能力,而且支持空间填充曲线作为时空索引,但不支持二级索引,当客户从多维度查询时需要建立多张表,数据存在冗余,存储成本非常高。


在实时计算的场景里,目前也缺少一个完备的支持时空数据的流引擎,导致很多客户会引入一个通用的流引擎或者直接用数据库来近似代替。


此外,这些数据库均不支持SQL接口,各个数据库的数据类型、访问接口均不一致,业务系统在接入不同的数据库时要进行大量的适配改造。


Lindorm作为一款阿里云推出的云原生超融合多模数据库,包含了流引擎、宽表引擎、对象引擎、搜索引擎等,那么自然少不了对时空数据的支持。最新发布的Lindorm已经深度融合了达摩院空天数据库引擎Ganos(下文统称为Lindorm Ganos),可以一站式的解决海量轨迹场景的存储和各类查询需求,弥补了各类NoSQL在时空方面的不足。


  • 标准化采用SQL接口和Geometry类型,用户可以像使用PostGIS一样来使用Lindorm Ganos。
  • 高性能一方面继承了Lindorm在写入、扩展性、成本等基础能力的优势;另一方面提供了时空主键索引、时空二级索引来应对多维度查询,在高效查询的同时无需为时空场景专门冗余一份数据。
  • 全面性支持Lindorm宽表引擎和流引擎,一套系统里既可以电子围栏这样的实时计算场景,也可以支持大规模历史数据的查询和统计,降低了解决方案的复杂性。

1.JPG

本文在Lindorm Ganos中对上述常用的时空场景进行测试,用过程和实际的数据展示Lindorm Ganos的具备的能力和特性。


1.时空范围查询


时空范围查询是时空领域的基础查询能力,这里所说的时空范围查询是一个统称,具体又可以分为:


  • 根据空间范围查找
  • 根据时间范围查找
  • 根据空间范围 + 时间范围查找


Lindorm Ganos提供了原生的时空数据类型、时空算子、时空主键索引、时空二级索引,避免为每一种查询冗余存储一份数据。

123.JPG

查找给定红色范围内的轨迹点


1.1 测试数据

本节以纽约出租车数据为例,来展示Ganos在空间范围查找、空间范围+时间范围查找轨迹的步骤和效果,并与相近的几个系统进行对比。


  • 轨迹数据

纽约2010年出租车轨迹数据,作为基础数据(数据下载:https://databank.illinois.edu/datasets/IDB-9610843。取medallion、pickup_datetime、pickup_longitude、pickup_latitude 四个字段的数据,排除脏数据,共158618394 行,写入数据原始大小7.6 GB。

  • 查询范围数据

纽约行政区划数据(数据下载:https://data.cityofnewyork.us/City-Government/Community-Districts/yfnk-k7r4,用来作为查询时的空间范围,共163个地理围栏范围。


1.2 测试环境

  • Lindorm Ganos测试集群:Lindorm三节点16核32GB,性能型云存储
  • 开源GeoMesa 3.0.0版本,底层存储为HBase测试集群:3节点独享 16核32GB,SSD云盘
  • MongoDB测试集群:3个Mongos为16核32GB(通用型);3个shard为16核64G(通用型)

1.3 测试内容

  • 针对海量轨迹的写入用时
  • 建立时空索引后的空间占用
  • 时空范围查询用时


  • 创建表和索引

Lindorm Ganos:使用SQL语法,压缩方式为ZSTD,同时为geom列创建空间索引。

CREATE TABLE foil_2010 (
  medallion VARCHAR,   
  pickup_datetime TIMESTAMP,
  geom GEOMETRY(POINT),
  primary key(z-order(geom), medallion)
) WITH (COMPRESSION='ZSTD');

GeoMesa(HBase):使用GeoMesa客户端,压缩方式为ZSTD,同时为geom列创建z2空间索引。限于篇幅,部分代码如下:

String schemaDescription = "medallion:String,pickup_datetime:Date,*geom:Point:srid=4326";
SimpleFeatureType simpleFeatureType = SimpleFeatureTypes.createType("foil_2010", schemaDescription);
simpleFeatureType.getUserData().put("geomesa.table.compression.enabled", true);
simpleFeatureType.getUserData().put("geomesa.table.compression.type", "zstd");
simpleFeatureType.getUserData().put("geomesa.indices.enabled", "z2");

MongoDB:压缩方式为ZSTD,开启sharding方式批量写入,同时为geom列创建2dsphere索引。限于篇幅,部分代码如下:

db.createCollection( "foil_2010", {storageEngine:{wiredTiger:{configString:'block_compressor=zstd'}}} );
//创建空间索引
db.foil_2010.createIndex({geom:"2dsphere"});
sh.enableSharding("test");
sh.shardCollection("test.foil_2010",{"_id":"hashed"});
......
collection.bulkWrite(rows);
  • 空间范围查询

Lindorm Ganos:使用SQL语法。

SELECT medallion
FROM foil_2010
WHERE ST_Contains(ST_GeomFromText('POLYGON ((...))'), geom);

GeoMesa(HBase):使用GeoTools的ECQL语法,并通过GeoTools的接口迭代获取数据。

ecqlPredicate = "CONTAINS(POLYGON ((...)) , geom)";
query  = new Query("foil_2010", ECQL.toFilter(ecqlPredicate));
result = datastore.getFeatureSource("foil_2010").getFeatures(query);
iterator = result.features();
while (iterator.hasNext()) {    iterator.next();}

MongoDB:添加Filter,并通过MongoDB接口迭代获取数据。

Bson filter = Filters.geoWithin("geom", new Polygon(new PolygonCoordinates(polygonCoords)));
MongoCursor<Document> cursor = collection.find(filter).iterator();
while (cursor.hasNext()) {
      cursor.next();
      }
  • 时空范围查询

Lindorm Ganos:使用SQL语法。

SELECT medallion
FROM foil_2010
WHERE ST_Contains(ST_GeomFromText('POLYGON ((...))'), geom)
AND pickup_datetime >= 'xxxx-xx-xx xx:xx:xx' 
AND pickup_datetime <= 'xxxx-xx-xx xx:xx:xx';

GeoMesa(HBase):使用GeoTools的ECQL语法,并通过GeoTools的接口迭代获取数据。

ecqlPredicate = "CONTAINS(POLYGON ((...)) , geom) AND pickup_datetime >= xxx AND pickup_datetime <= xxx";
query = new Query("foil_2010", ECQL.toFilter(ecqlPredicate));
result = datastore.getFeatureSource("foil_2010").getFeatures(query);
iterator = result.features();
while (iterator.hasNext()) {
       iterator.next();
       }

MongoDB:添加多个Filter,并通过MongoDB接口迭代获取数据。

Bson filter = Filters.and(Filters.geoWithin("geom", new Polygon(new PolygonCoordinates(polygonCoords))), Filters.and(Filters.gte("pickup_datetime",startTime), Filters.lte("pickup_datetime", endTime));
MongoCursor<Document> cursor = collection.find(filter).iterator();
while (cursor.hasNext()) {
      cursor.next();
      }

可以看出,创建表以及查询时,Lindorm Ganos使用的SQL语法都是最简洁的,使用非常方便。


1.4 测试结果

  • 写入用时

Lindorm Ganos继承了Lindorm高效的写入能力,写入耗时为GeoMesa(HBase)的1/2,为MongoDB的1/5

数据库 用时
Lindorm Ganos 7 min
GeoMesa(HBase) 13 min
MongoDB 34 min


  • 存储空间占用


在建立空间索引的情况下,Lindorm Ganos占用的存储空间更少,为GeoMesa(HBase)的80%,为MongoDB的47%

数据库

表大小

空间索引大小

Lindorm Ganos

4.7 GB

无额外空间,主键作索引

GeoMesa(HBase)

5.9 GB

无额外空间,主键作索引

MongoDB

8.2 GB

1.6 GB


  • 空间范围查询用时


空间范围查询场景下,随着返回结果的增加,几个系统的查询用时也在增加。Lindorm Ganos在大部分的查询中,查询性能都是大幅领先GeoMesa(HBase)和MongoDB,耗时分别为GeoMesa(HBase)的1/3,MongoDB的1/2

2.png


  • 时空范围查询用时


时间+空间范围查询场景下,Lindorm Ganos在大部分的查询中,查询性能都是领先GeoMesa(HBase)和MongoDB,耗时分别是二者的1/31/2左右,个别查询耗时与二者持平。

3.png


2.电子围栏


实时监控车辆的运行轨迹,判断车辆是否偏离设定的路线也是一个强需求,这类查询一般称为电子围栏或地理围栏判断。与时空范围查询相反,电子围栏是给定一个位置点,来判断该点是否在某个/些范围内。这类查询对实时性的要求比较高,且并发也较大,为了应对这种场景,Ganos结合Lindorm流引擎,可以以流计算的方式来处理。


本节以实时电子围栏为例,来展示Ganos在这个场景中的应用。除电子围栏外,Lindorm 流引擎也支持车辆出入围栏告警等用法。

4.JPG

实时监控车辆是否偏离预定线路


2.1 测试数据

使用北京市公交车线路数据,数据集内共包含1543条线路,数据类型为LineString。我们先通过 ST_Buffer 缓冲区计算函数将线路扩展为宽度 10 米的Polygon,这些道路的Polygon作为电子围栏。

2.2 测试环境

  • Lindorm Ganos 宽表:4核 16GB 2节点
  • Lindorm Streams 引擎:32核 64GB 2节点,Topic 分别为 4/8/12/16 partition,1 Producer 1 Consumer

2.3 测试内容

判断实时写入的轨迹点在哪个线路上,即需要为每个Point计算出当前所在的Polygon对象,同时统计不同吞吐量下的系统延迟。

  • 写入数据

将线路的route_id以及对应的Polygon存储到 Lindorm 宽表,结构如下:

# lindorm-cli
create table bj_busline (route_id int,
                         poly geometry(polygon),
                         primary key(route_id));
  • 创建流引擎映射表

在流引擎中创建一张映射表,指向Lindorm路线表bj_busline,这样就可以在流引擎中使用宽表中的数据。同时为映射表创建时空索引来加速实时计算,至此,地理围栏数据存在于流引擎中。

CREATE External Table dimTable
WITH (
   table_type = 'lindorm.table', 
   table_name = 'bj_busline',
   endpoint = 'lindorm-1:30020',
   output_batchsize=500,
   cache_type = 'LRU',
   cache_ttl = 1800000,
   ganos_index_type='RTREE',
   ganos_index_polygon_col_name='poly'
   );
  • 创建写入流和输出流

接下来创建写入流和输出流来分别接收写入的轨迹点数据和计算的结果。

CREATE STREAM input_stream ( 
  p_id int,
  p_location geometry(point), 
  time bigint)
WITH (stream_topic='input', value_format='JSON', key_value = 'p_id');
CREATE STREAM output_stream ( 
  p_id int,
  p_location geometry(point),
  route_id varchar,  
  time bigint)
WITH (stream_topic='output', value_format='JSON', key_value = 'p_id');
  • 计算链路

基于 Lindorm 流引擎连续查询(Continuous Query,简称 CQ)创建计算链路,该CQ会从写入流中取出数据,并通过Join计算之后,将结果写入到 output_stream 中:

CREATE CQ busRouteJoin INSERT INTO output_stream
SELECT
l.p_id AS p_id,
l.p_location AS p_location,
r.route_name AS route,
l.time AS time
FROM input_stream l LEFT JOIN dimTable r ON ST_Contains(r.poly, l.p_location);

此处 p_id 为上报点位 id,p_location 为点位具体信息,route 为匹配到的线路名称,time 为时间戳。当轨迹点流入后,会与地理围栏比对,并输出每个所在的线路名称,若点并不在某条线路上,则对应的 route 结果为 null。

p_id

p_location

route

time

0

Point(116.4132, 40.0568)

984路区间

2022-09-07 15:18:22

1

Point(116.4133, 40.0569)

null

2022-09-07 15:18:25

...





2.4 测试结果


下面是不同流入速度和 partition 下,对 1543 个地理围栏判断从生产到消费延迟。可以看到随着点流入速度的提高,系统的延迟也明显增大,这是因为在上述的计算链路里,每流入1个点则流出1543条判断结果,所以计算强度是千倍的提升。同时,在同一流入速度下,随着partition的增加,系统的延迟会有降低。

5.png

3.周边查询


周边查询一般不加时间条件,比如需要查询周边300米内有哪些餐馆,周围2公里有哪些出租车。与时空范围查询的区别点在于:

  • 周边查询一般只会指定中心点以及查询距离,距离的度量单位一般为米或千米,而时空范围查询一般是含有一系列坐标点的Polygon对象。
  • 计算距离时,一般是指地球椭球体上的距离,而不是平面坐标系的距离。

235.png

周边查询示意图

3.1 测试内容

利用纽约出租车数据,查询所在位置点周边范围内的车辆。由于GeoMesa不支持球面距离计算DWithin,我们只与MongoDB的同功能进行对比,比较不同查询半径和返回结果数量级的查询性能。


数据集、建表和写入的流程与第1节相同,此处不再重复。


  • 查询语句示例

Lindorm Ganos:使用SQL语法

SELECT medallion
FROM foil_2010
WHERE ST_DWithinSphere(ST_GeomFromText('POINT (120.177206 30.273576)'), geom, 300e0);

MongoDB

Bson filter = Filters.nearSphere("geom", new Point(new Position(120.177206, 30.273576)), 300.0, 0.0);
MongoCursor<Document> cursor = collection.find(filter).iterator();
while (cursor.hasNext()) { 
   cursor.next();
   }

3.2 测试结果

周边查询的用时与查询半径和返回结果数量都有关系,Lindorm Ganos在不同数量级的查询半径、返回结果数的情况下,查询性能均领先于MongoDB。

6.png

总结


我们通过几个时空领域常见的查询场景为切入,对Lindorm Ganos和类似的几个系统进行了测试。从上面的测试过程和结果来看,相比于其他的系统,Lindorm Ganos:

  • 可以通过SQL语法很便捷的处理各类查询场景,使用起来比较简单
  • 可以与Lindorm宽表引擎、流引擎深度的融合,覆盖大部分常用的场景,减少了解决方案的复杂性
  • 在存储成本上低于GeoMesa(HBase)以及MongoDB,可降低20%~50%的存储空间
  • 在查询性能上,大部分查询场景的性能要大幅领先业界已有系统(2~3倍


综上,Lindorm Ganos在轨迹的写入速度、存储成本、查询性能以及易用性上优势较为明显,完全可以满足车联网、出行等领域对轨迹系统的处理需求。


 / End /  

相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
|
SQL 存储 并行计算
Lindorm Ganos 一条 SQL 计算轨迹
Lindorm Ganos 针对轨迹距离计算场景提供了内置函数 ST_Length_Rows,结合原生时空二级索引和时空聚合计算下推技术,能够高效过滤数据并并行执行运算任务。该方案通过主键索引和时空索引快速过滤数据,并利用多Region并行计算轨迹点距离,适用于车联网等场景。具体步骤包括根据车辆识别代码和时间戳过滤数据、范围过滤轨迹点以及并行计算距离。使用限制包括只支持点类型列聚合运算及表中轨迹点需按顺序排列等。测试结果显示,Lindorm Ganos 在不同数据量下均能实现秒级响应。
30 3
|
2月前
|
消息中间件 存储 SQL
关于Lindorm Ganos
Lindorm 是阿里云推出的云原生超融合多模数据库,集成了宽表、时序、搜索、文件等多种引擎。深度融合的 Lindorm Ganos 时空数据库引擎,能够高效处理海量移动对象的存储、管理和查询需求,弥补了 NoSQL 数据库在时空数据处理上的不足。Ganos 具备原生时空数据类型、多层级索引能力和广适应兼容性,支持标准 SQL 语法,显著提升了计算效率和查询性能。相较传统方案,Ganos 在多种场景下性能提升 3-5 倍,并大幅降低存储计算成本。
62 0
|
6月前
|
消息中间件 存储 Kafka
Lindorm Ganos轨迹点快速聚合能力简介
本文介绍了Ganos时空数据库在Lindorm流引擎上的全新能力与最佳实践,帮助客户解决车辆网场景中轨迹点实时聚合生成轨迹线的能力。Lindorm Ganos实现了Lindorm宽表、流、计算等引擎在时空领域的打通,支持原生时空类型与多种时空算子,支持多种不同的时空索引,不仅可用于传统的周边查询,还面向了历史轨迹的查询分析、实时地理围栏查询、点面查询等更加复杂的业务需求。
|
6月前
|
存储 Cloud Native 搜索推荐
Lindorm Ganos
Lindorm Ganos 是阿里云推出的一款云原生超融合多模数据库,它集成了流引擎、宽表引擎、对象引擎、搜索引擎等多种功能,可用于解决海量数据的存储和查询问题。其中,Ganos 时空引擎是 Lindorm 的一个重要组件,主要负责处理时空数据。
79 3
|
6月前
|
存储 SQL 达摩院
Lindorm Ganos轨迹点
Lindorm Ganos 是阿里云推出的一款云原生超融合多模数据库,它集成了达摩院空天数据库引擎 Ganos
72 1
|
存储 消息中间件 SQL
基于Lindorm Ganos的车辆实时行为分析
本文介绍了Ganos时空数据库在Lindorm流引擎上的全新能力与最佳实践,帮助客户解决车辆网场景中实时时空数据分析的需求。Lindorm Ganos实现了Lindorm宽表、流、计算等引擎在时空领域的打通,支持原生时空类型与多种时空算子,支持多种不同的时空索引,不仅可用于传统的周边查询,还面向了历史轨迹的查询分析、地理围栏查询、点面查询等更加复杂的业务需求。
|
存储 SQL NoSQL
NoSQL“小钢炮”,Lindorm时空引擎Ganos轨迹处理实测
Lindorm作为一款阿里云推出的云原生超融合多模数据库,包含了流引擎、宽表引擎、对象引擎、搜索引擎等。最新发布的Lindorm已经深度融合了达摩院空天数据库引擎Ganos(Lindorm Ganos),可以一站式的解决海量轨迹场景的存储和各类查询需求,本文通过对Lindorm Ganos在常用的时空场景进行测试,用过程和实际的数据展示Lindorm Ganos的具备的能力和特性。
NoSQL“小钢炮”,Lindorm时空引擎Ganos轨迹处理实测
|
SQL 分布式计算 并行计算
用 Lindorm Ganos 一条 SQL 计算轨迹距离
Lindorm 多模数据库提供宽表、时序、搜索、文本、空间等多种数据模型,面向互联网、IoT、车联网等场景,是阿里巴巴核心业务提供关键支撑的数据库之一。Lindorm Ganos 将 Ganos 对时空数据的处理能力深度融合到 Lindorm 中,提供原生的时空数据类型和时空算子,内置时空主键索引和时空二级索引,将时空算子下推并优化了查询计划,可以很好地满足车联网业务对轨迹、位置、范围等数据处理的需求。针对轨迹距离计算场景,Lindorm Ganos 内置 ST_Length_Rows 函数来高效实现轨迹距离计算。
用 Lindorm Ganos 一条 SQL 计算轨迹距离
|
存储 达摩院 监控
新功能!Lindorm Ganos 轨迹出入点统计
阿里云云原生超融合多模数据库Lindorm广泛支持宽表、时序、对象、文本、队列、空间等多种数据模型,Lindorm Ganos作为Lindorm的时空引擎,将达摩院空天数据库引擎的时空数据库技术与Lindorm深度融合,为Lindorm提供了一站式解决海量轨迹场景的存储和各类查询问题的能力。本文介绍Lindorm Ganos在轨迹出入点统计应用场景下的解决方案和能力优势。
新功能!Lindorm Ganos 轨迹出入点统计
|
5月前
|
存储 SQL 多模数据库
多模数据库Lindorm再升级:对接Dataphin,打通数据治理“最后一公里”
Lindorm通过与Dataphin的深度整合,进一步解决了数据集成和数据治理的问题,为企业提供更加高效和更具性价比的方案。
多模数据库Lindorm再升级:对接Dataphin,打通数据治理“最后一公里”

相关产品

  • 云原生多模数据库 Lindorm
  • 下一篇
    无影云桌面