PostgreSQL 实时位置跟踪+轨迹分析系统实践 - 单机顶千亿轨迹/天

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS PostgreSQL Serverless,0.5-4RCU 50GB 3个月
推荐场景:
对影评进行热评分析
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介:

标签

PostgreSQL , PostGIS , 动态更新位置 , 轨迹跟踪 , 空间分析 , 时空分析


背景

随着移动设备的普及,越来越多的业务具备了时空属性,例如快递,试试跟踪包裹、快递员位置。例如实体,具备了空间属性。

例如餐饮配送,送货员位置属性。例如车辆,实时位置。等等。

其中两大需求包括:

1、对象位置实时跟踪,例如实时查询某个位点附近、或某个多边形区域内的送货员。

2、对象位置轨迹记录和分析。结合地图,分析轨迹,结合路由算法,预测、生成最佳路径等。

DEMO

以快递配送为例,GPS设备实时上报快递员轨迹,写入位置跟踪系统,同时将轨迹记录永久保存到轨迹分析系统。

由于快递员可能在配送过程中停留时间较长(比如在某个小区配送时),上报的多条位置可能变化并不大,同时考虑到数据库更新消耗,以及位置的时效性,可以避免一些点的更新(打个比方,上一次位置和当前位置变化量在50米时,不更新)。

动态更新可以减少数据库的更新量,提高整体吞吐能力。

设计

pic

实时位置更新

1、建表

create table t_pos (  
  uid int primary key,   -- 传感器、快递员、车辆、。。。对象ID  
  pos point,             -- 位置  
  mod_time timestamp     -- 最后修改时间  
);  
  
create index idx_t_pos_1 on t_pos using gist (pos);  

真实环境中,我们可以使用PostGIS空间数据库插件,使用geometry数据类型来存储经纬度点。

create extension postgis;  
  
create table t_pos (  
  uid int primary key,   -- 传感器、快递员、车辆、。。。对象ID  
  pos geometry,          -- 位置  
  mod_time timestamp     -- 最后修改时间  
);  
  
create index idx_t_pos_1 on t_pos using gist (pos);  

2、上报位置,自动根据移动范围,更新位置。

例如,移动距离50米以内,不更新。

insert into t_pos values (?, st_setsrid(st_makepoint($lat, $lon), 4326), now())  
on conflict (uid)  
do update set pos=excluded.pos, mod_time=excluded.mod_time  
where st_distancespheroid(t_pos.pos, excluded.pos, 'SPHEROID["WGS84",6378137,298.257223563]') > ?;  -- 超过多少米不更新  

历史轨迹保存

通常终端会批量上报数据,例如每隔10秒上报10秒内采集的点,一次上报的数据可能包含多个点,在PostgreSQL中可以以数组存储。

create table t_pos_hist (  
  uid int,                  -- 传感器、快递员、车辆、。。。对象ID  
  pos point[],              -- 批量上报的位置  
  crt_time timestamp[]      -- 批量上报的时间点  
);   
  
create index idx_t_pos_hist_uid on t_pos_hist (uid);                 -- 对象ID  
create index idx_t_pos_hist_crt_time on t_pos_hist ((crt_time[1]));    -- 对每批数据的起始时间创建索引  

有必要的话,可以多存一个时间字段,用于分区。

历史轨迹分析

动态位置变更压测

写入并合并,同时判断当距离大于50时,才更新,否则不更新。

(测试)如果使用point类型,则使用如下SQL

insert into t_pos values (1, point(1,1), now())  
on conflict (uid)  
do update set pos=excluded.pos, mod_time=excluded.mod_time  
where t_pos.pos <-> excluded.pos > 50;  

(实际生产)如果使用PostGIS的geometry类型,则使用如下SQL

insert into t_pos values (1, st_setsrid(st_makepoint(120, 71), 4326), now())  
on conflict (uid)  
do update set pos=excluded.pos, mod_time=excluded.mod_time  
where st_distancespheroid(t_pos.pos, excluded.pos, 'SPHEROID["WGS84",6378137,298.257223563]') > 50;  

压测

首先生成1亿随机空间对象数据。

postgres=# insert into t_pos select generate_series(1,100000000), point(random()*10000, random()*10000), now();  
INSERT 0 100000000  
Time: 250039.193 ms (04:10.039)  

压测脚本如下,1亿空间对象,测试动态更新性能(距离50以内,不更新)。

vi test.sql    
  
\set uid random(1,100000000)    
insert into t_pos    
select uid, point(pos[0]+random()*100-50, pos[1]+random()*100-50), now() from t_pos where uid=:uid   
on conflict (uid)   
do update set pos=excluded.pos, mod_time=excluded.mod_time   
where t_pos.pos <-> excluded.pos > 50;   

压测结果,动态更新 21.6万点/s,187亿点/天。

pgbench -M prepared -n -r -P 1 -f ./test.sql -c 64 -j 64 -T 120   
  
number of transactions actually processed: 26014936
latency average = 0.295 ms
latency stddev = 0.163 ms
tps = 216767.645838 (including connections establishing)
tps = 216786.403543 (excluding connections establishing)

轨迹写入压测

每个UID,每批写入50条:写入速度约 467.5万点/s,4039亿点/天。

压测时,写多表,压测使用动态SQL。

do language plpgsql $$  
declare  
begin  
  for i in 0..127 loop  
    execute 'create table t_pos_hist'||i||' (like t_pos_hist including all)';  
  end loop;  
end;  
$$;  
create or replace function import_test(int) returns void as $$  
declare  
begin  
  execute format('insert into t_pos_hist%s values (%s, %L, %L)', mod($1, 128), $1,   
  array[point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1), point(1,1)] ,  
  array['2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10', '2018-01-01 10:10:10']);  
end;  
$$ language plpgsql strict;  
vi test1.sql  
  
\set uid random(1,100000000)  
select import_test(:uid);  
pgbench -M prepared -n -r -P 1 -f ./test1.sql -c 56 -j 56 -T 120   
  
  
number of transactions actually processed: 11220725  
latency average = 0.599 ms  
latency stddev = 5.452 ms  
tps = 93504.532256 (including connections establishing)  
tps = 93512.274135 (excluding connections establishing)  

黑科技

1、块级索引(BRIN),在时序属性字段上,建立块级索引,既能达到高效检索目的,又能节约索引空间,还能加速写入。

《PostgreSQL BRIN索引的pages_per_range选项优化与内核代码优化思考》

《万亿级电商广告 - brin黑科技带你(最低成本)玩转毫秒级圈人(视觉挖掘姊妹篇) - 阿里云RDS PostgreSQL, HybridDB for PostgreSQL最佳实践》

《PostGIS空间索引(GiST、BRIN、R-Tree)选择、优化 - 阿里云RDS PostgreSQL最佳实践》

《自动选择正确索引访问接口(btree,hash,gin,gist,sp-gist,brin,bitmap...)的方法》

《PostgreSQL 并行写入堆表,如何保证时序线性存储 - BRIN索引优化》

《PostgreSQL 9种索引的原理和应用场景》

2、阿里云HDB PG特性:sort key , metascan

与BRIN类似,适合线性数据,自动建立块级元数据(取值范围、平均值、CNT、SUM等)进行过滤。

3、空间索引

GiST, SP-GiST空间索引,适合空间数据、以及其他异构数据。

4、动态合并写,根据位置变化量,自动判断是否需要合并更新。

insert on conflict语法,在do update里面,可以进行条件过滤,当位置变化超过N米时,才进行更新。

5、数组、JSON、KV等多值类型。

特别适合多值属性,例如批量上传的轨迹,通常GPS终端上报位置并不是实时的,可能存在一定的 延迟(例如批量上报)。使用数组、JSON都可以存储。

如果使用数组存储,将来分析轨迹时,依旧可以unnest解开,绘制轨迹。

性能

1、动态位置变更:1亿被跟踪对象,TPS:21.6万,动态更新21.6万点/s,187亿点/天。

2、轨迹写入:tps约10万,写入467.5万点/s,4039亿点/天。

参考

《PostGIS 空间数据学习建议》

《PostgreSQL + PostGIS + SFCGAL 优雅的处理3D数据》

《PostGIS 距离计算建议 - 投影 与 球 坐标系, geometry 与 geography 类型》

《PostgreSQL 10 + PostGIS + Sharding(pg_pathman) + MySQL(fdw外部表) on ECS 部署指南(适合新用户)》

《PostGIS 空间索引(GiST、BRIN、R-Tree)选择、优化 - 阿里云RDS PostgreSQL最佳实践》

《PostGIS 坐标转换(SRID)的边界问题引发的专业知识 - ST_Transform》

《无人驾驶背后的技术 - PostGIS点云(pointcloud)应用 - 2》

《无人驾驶背后的技术 - PostGIS点云(pointcloud)应用 - 1》

《geohash vs PostGIS》

《视觉挖掘与PostGIS空间数据库的完美邂逅 - 广告营销\圈人》

《PostGIS 点面叠加视觉判断输出》

《PostGIS 多点几何类型 空字符构造异常CASE》

《开放地图OpenStreetMap与PostGIS的三生三世十里桃花》

《PostGIS 地理信息、栅格数据 多核并行处理(st_memunion, st_union)》

《蜂巢的艺术与技术价值 - PostgreSQL PostGIS's hex-grid》

《如何建立GIS测试环境 - 将openstreetmap的样本数据导入PostgreSQL PostGIS库》

《GIS附近查找性能优化 - PostGIS long lat geometry distance search tuning using gist knn function》

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
存储 关系型数据库 物联网
沉浸式学习PostgreSQL|PolarDB 14: 共享单车、徒步、旅游、网约车轨迹查询
本文的目的是帮助你了解如何设计轨迹表, 如何高性能的写入、查询、分析轨迹数据.
707 0
|
关系型数据库 物联网 PostgreSQL
沉浸式学习PostgreSQL|PolarDB 11: 物联网(IoT)、监控系统、应用日志、用户行为记录等场景 - 时序数据高吞吐存取分析
物联网场景, 通常有大量的传感器(例如水质监控、气象监测、新能源汽车上的大量传感器)不断探测最新数据并上报到数据库. 监控系统, 通常也会有采集程序不断的读取被监控指标(例如CPU、网络数据包转发、磁盘的IOPS和BW占用情况、内存的使用率等等), 同时将监控数据上报到数据库. 应用日志、用户行为日志, 也就有同样的特征, 不断产生并上报到数据库. 以上数据具有时序特征, 对数据库的关键能力要求如下: 数据高速写入 高速按时间区间读取和分析, 目的是发现异常, 分析规律. 尽量节省存储空间
779 1
|
关系型数据库 数据库 PostgreSQL
使用 Docker 在 Windows、Mac 和 Linux 系统轻松部署 PostgreSQL 数据库
使用 Docker 在 Windows、Mac 和 Linux 系统轻松部署 PostgreSQL 数据库
541 1
|
3月前
|
Oracle NoSQL 关系型数据库
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
主流数据库对比:MySQL、PostgreSQL、Oracle和Redis的优缺点分析
588 2
|
6月前
|
自然语言处理 关系型数据库 数据库
技术经验解读:【转】PostgreSQL的FTI(TSearch)与中文全文索引的实践
技术经验解读:【转】PostgreSQL的FTI(TSearch)与中文全文索引的实践
72 0
|
关系型数据库 定位技术 分布式数据库
沉浸式学习PostgreSQL|PolarDB 18: 通过GIS轨迹相似伴随|时态分析|轨迹驻点识别等技术对拐卖、诱骗场景进行侦查
本文主要教大家怎么用好数据库, 而不是怎么运维管理数据库、怎么开发数据库内核.
1327 1
|
关系型数据库 Linux 数据库
Linux系统之安装PostgreSQL数据库
Linux系统之安装PostgreSQL数据库
1189 1
|
7月前
|
存储 关系型数据库 MySQL
TiDB与MySQL、PostgreSQL等数据库的比较分析
【2月更文挑战第25天】本文将对TiDB、MySQL和PostgreSQL等数据库进行详细的比较分析,探讨它们各自的优势和劣势。TiDB作为一款分布式关系型数据库,在扩展性、并发性能等方面表现突出;MySQL以其易用性和成熟性受到广泛应用;PostgreSQL则在数据完整性、扩展性等方面具有优势。通过对比这些数据库的特点和适用场景,帮助企业更好地选择适合自己业务需求的数据库系统。
1192 4
|
7月前
|
弹性计算 关系型数据库 数据库
开源PostgreSQL在倚天ECS上的最佳优化实践
本文基于倚天ECS硬件平台,以自顶向下的方式从上层应用、到基础软件,再到底层芯片硬件,通过应用与芯片的硬件特性的亲和性分析,实现PostgreSQL与倚天芯片软硬协同的深度优化,充分使能倚天硬件性能,帮助开源PostgreSQL应用实现性能提升。
|
7月前
|
SQL 运维 关系型数据库
基于AnalyticDB PostgreSQL的实时物化视图研发实践
AnalyticDB PostgreSQL版提供了实时物化视图功能,相较于普通(非实时)物化视图,实时物化视图无需手动调用刷新命令,即可实现数据更新时自动同步刷新物化视图。当基表发生变化时,构建在基表上的实时物化视图将会自动更新。AnalyticDB PostgreSQL企业数据智能平台是构建数据智能的全流程平台,提供可视化实时任务开发 + 实时数据洞察,让您轻松平移离线任务,使用SQL和简单配置即可完成整个实时数仓的搭建。
144005 8

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版