http://www.gissky.net- GIS空间站

我要投稿 投稿指南 RSS订阅 网站资讯通告:
搜索: 您现在的位置: GIS空间站 >> 技术专栏 >> 地理信息 >> 正文

轨迹系列——记某真实项目中轨迹展示查询效率优化方案一(初步设计) - 李晓晖

作者:博客园    文章来源:博客园    点击数:    更新时间:2017-8-1
摘要:文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.背景 准确说,该项目的迹展示涉及到两个方面,一个是轨迹查询展示,一个是轨迹信息挖掘展示。随着轨迹表数据的增加,以及轨迹信息挖掘涉及到的案卷表数据的增加,项目上目前出现了比较明显的轨迹展示性能问题。 这里,我尝试从代码流程逻辑、GPS采集优化、数据库常用优化(轨迹历史数据迁移和索引建立)、表结构重构,Redis缓存的引用五个方面来进行优化。 2.代码流程逻辑优化 2.1公有数据的合理复用 在最初设计流程时,轨迹展示和轨迹信息挖掘是两个相对独立部分,一个负责地图端的轨迹展示、一个负责提供给业务端(MIS和手机)来调用展示轨迹挖掘信息,所以致使两个功能成为了各自独立的接口。 但是随着历史轨迹表数据的激增,这种分离方式出现了明显的性能弊端——即轨迹查询结果的复用。 轨
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处: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/

                                                                            如果您觉得本文确实帮助了您,可以微信扫一扫,进行小额的打赏和鼓励,谢谢 ^_^

                                        

 

Tags:GIS,地理信息  
责任编辑:gissky
关于我们 - 联系我们 - 广告服务 - 友情链接 - 网站地图 - 中国地图