文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
1. 背景
准确说,该项目的迹展示涉及到两个方面,一个是轨迹查询展示,一个是轨迹信息挖掘展示。随着轨迹表数据的增加,以及轨迹信息挖掘涉及到的案卷表数据的增加,项目上目前出现了比较明显的轨迹展示性能问题。
这里,我尝试从代码流程逻辑、GPS采集优化、数据库常用优化(轨迹历史数据迁移和索引建立)、表结构重构,Redis缓存的引用五个方面来进行优化。
2. 代码流程逻辑优化
2.1公有数据的合理复用
在最初设计流程时,轨迹展示和轨迹信息挖掘是两个相对独立部分,一个负责地图端的轨迹展示、一个负责提供给业务端(MIS和手机)来调用展示轨迹挖掘信息,所以致使两个功能成为了各自独立的接口。
但是随着历史轨迹表数据的激增,这种分离方式出现了明显的性能弊端——即轨迹查询结果的复用。
轨迹信息挖掘流程的第一步,需要获取到待挖掘的所有轨迹点。而这些点在轨迹展示时,就已经获取到了。以之前的两个业务独立的逻辑,将会导致轨迹获取的重复查询。
这里,我建议将流程稍作修改,如下图所示:
2.2轨迹信息挖掘的查询瘦身
在最初的轨迹信息与案卷关联的挖掘中,我们最开始查询四张表:案卷表(dlmis.to_rec)、核查核实表(dlmis.to_mi_patrol_task)、历史案卷表(dlhist.to_his_rec)、历史核查核实表(dlhist.to_his_mi_patrol_task)。但是,经过测试发现历史案卷表和历史核查表往往很大,是查询的瓶颈所在。所以我们增加了一个参数(histrec)来进行表的查询控制。
当histrec值为false时,查询案卷表和核查核实表这一组;当为ture时,查询历史案卷表和历史核查核实表那一组。
由于系统默认是展示当天轨迹信息挖掘,所以histrec参数为true,从而避免了初始查询时对历史案卷那一组的查询。
3.GPS采集优化
在GPS采集源头,通过对行为者的状态分析(停留、行走、跑步等),实现对GPS采集频率的控制。并且通过对GPS信号、位置精度等附加信息分析,过滤掉无效GPS以及室内GPS数据。从而增加有效GPS的同时,实现GPS采集存储量的减负。
4.数据库常用优化
4.1历史轨迹迁移
从业务层面分析,得出针对一个月前的轨迹查询在业务上来讲基本是无作用的(一个月前的绩效已考核、工资已发放)。甚至在该项目现场,七天前的轨迹,也不是业主所关心的。所以这里采用一个定时任务,在每天深夜(避免迁徙中对正在上传的轨迹造成影响)进行轨迹的迁徙,轨迹表中只保留最近七天的轨迹,而每一个当天的轨迹均移至历史轨迹表中。据目前初步统计,七天的轨迹量大概在80W条上下,数量得到很好的控制。
4.2轨迹表上建立索引
GIS端的轨迹查询语句为:
select aa.coordinate_x as coordinatex,aa.coordinate_y as coordinatey,to_char(aa.update_time, 'YYYY-MM-DD HH24:MI:SS') as logtime from dlmis.tr_log_patrol_pos aa where aa.update_time>= ? and aa.update_time <? and aa.patrol_id = ? and revised_coord_y<>-1 and aa.coordinate_x>0 and aa.coordinate_y >0 order by aa.update_time
以patrol_id和update_time分别建立索引:
5.表结构重构
针对轨迹迁徙方案,依然存在隐患,即如果真出现需要对一个月前的历史轨迹查询时,效率问题无法回避。这里以大表改小表的思路进行发散,在暂时不考虑某些项目上可能造成的影响,提出两种表结构重构的方案。
5.1分表方案(方案一)
假设,我们每隔一周(以一周为例)建立一个轨迹表,表中只存放该周的轨迹,那么每周轨迹表中的数据量将大大减少。表的命名以年_周,比如(2017_18,表示2017年18周),在查询轨迹时,算出查询时间所对应的轨迹表,进行查询即可。
5.2轨迹摘要表的运用(方案二)
提出该方案的设想是,我们以降低数据冗余、减少磁盘读操作,在分析业务的基础上进行设计。以下为目前的轨迹表:
我们观察历史轨迹表,可以发现一个人一天可以出现一千条数据。这些数据中,人员ID为重复信息,人员的速度、角度、道路等等均是轨迹查询中不需要的字段。针对这种现象,我们提出一个轨迹摘要表的概念,我将该表设计为如下:
Id(流水号) | patrolID(监督员编号) | Date(日期,单位天) | 报文(blob二进制) |
其中最核心的是报文,报文中我们将以(x,y,createtime)的格式,转换成二进制方式存储当天的所有有效轨迹。
这样,轨迹摘要中针对某个监督员的轨迹信息,将只有一条记录了。如果要查询某天的轨迹,我们只需要date和partolid进行过滤即可获得报文,然后解析报文。同时查询的效率会大大提高,假设一个人之前一天有1000条数据,那么现在只有一条数据。之前3个月1000W条数据,那么现在将只有1W条数据。
这里,涉及到报文内容的实时更新,如何能有效实现报文的追加更新呢?这里,引出我们的另一个优化,Redis缓存的应用。
6.Redis的运用
轨迹的写入,无论是针对轨迹摘要表,还是针对原来的轨迹表,均是一个不断产生开销的操作。而且针对轨迹表,查询最高的应该是当天轨迹查询。所以,针对当天不断上报的轨迹,我们可以将其都先存入redis中,在通过定时任务,于深夜同步写入至轨迹表中。
同样,查询轨迹时,针对当天轨迹的查询,也优先从redis中获取。
7.总结
该项目的轨迹优化方案,建议以三步走战略来进行:
a.先完成代码逻辑、数据库常用优化,然后观察效果。
b.如果效果一般,再进行Redis运用的改造。
c.最后,代价最大的表结构重构,个人觉得效果会很好,但是极有可能对现有业务等造成影响。
-----欢迎转载,但保留版权,请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/
如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^