文章版權由作者李曉暉和博客園共有,若轉載請於明顯處標明出處: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/
如果您覺得本文確實幫助了您,可以微信掃一掃,進行小額的打賞和鼓勵,謝謝 ^_^