PostgreSQL 实时位置跟踪
作者:互联网
背景
随着移动设备的普及,越来越多的业务具备了时空属性,例如快递,试试跟踪包裹、快递员位置。例如实体,具备了空间属性。
例如餐饮配送,送货员位置属性。例如车辆,实时位置。等等。
其中两大需求包括:
1、对象位置实时跟踪,例如实时查询某个位点附近、或某个多边形区域内的送货员。
2、对象位置轨迹记录和分析。结合地图,分析轨迹,结合路由算法,预测、生成最佳路径等。
DEMO
以快递配送为例,GPS设备实时上报快递员轨迹,写入位置跟踪系统,同时将轨迹记录永久保存到轨迹分析系统。
由于快递员可能在配送过程中停留时间较长(比如在某个小区配送时),上报的多条位置可能变化并不大,同时考虑到数据库更新消耗,以及位置的时效性,可以避免一些点的更新(打个比方,上一次位置和当前位置变化量在50米时,不更新)。
动态更新可以减少数据库的更新量,提高整体吞吐能力。
设计
实时位置更新
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])); -- 对每批数据的起始时间创建索引
有必要的话,可以多存一个时间字段,用于分区。