需求分析
每台设备上,增加当前设备运行的程序,以及历史运行的程序列表。
点击历史运行的程序列表,显示被点击程序运行的循环时间。
BU_Machine_CurrProgram
目前公司在厂区内布置了50台设备,服务器上有个定时任务,每隔10秒钟扫描50台设备上正在运行的程序,然后更新BU_Machine_CurrProgram表中的数据
换言之,BU_Machine_CurrProgram表中永远有50条记录,存放着设备当前正在运行的程序。
BU_Machine_CurrProgramList
select count(1) from BU_Machine_CurrProgramList; – 1526
同时,该定时任务还会扫描设备硬盘内,正在执行和等待执行的任务列表(所有的任务清单),将其插入到BU_Machine_CurrProgramList表中。
BU_Machine_CurrProgram存放的是设备当前正在运行的程序文件(update
)。
BU_Machine_CurrProgramList存放的是设备当前硬盘中,所有的程序文件(insert
)。
两种操作的不同,导致数据量千差万别。
(假如A设备正在执行001程序,执行120秒,同时硬盘上存储着001~099共100个程序)
此时BU_Machine_CurrProgram表中存放着A设备的一条记录,001程序。
但是BU_Machine_CurrProgramList,会存放12次A设备上的所有程序文件,即1200条记录,这还仅仅是一台设备,仅仅是100条记录)
如果是50台设备,如果每台设备的硬盘能存放1000份程序文件呢?无法想象。
BU_Machine_CurrProgramList表中的数据,应该在定时任务10秒读取任务清单后,先验证该清单在数据库中是否存在,如果存在,则不插入。
幸运的是,设备上的硬盘中,如果程序文件装满,就会触发清空操作。
此时BU_Machine_CurrProgramList表中的数据也会被清空。
BU_Machine_Program_History
最不幸的事情来了,BU_Machine_Program_History存放的是程序历史记录,即BU_Machine_CurrProgramList中的数据总会被备份到该表中,而且该表的数据永远也不会被清空。
select count(1) from BU_Machine_Program_History; – 33585357
该表中的数据,目前是33450148条,整整三千多万条。
一年就能上亿条数据,我滴乖乖。
因为数据量太大,所以目前是点击设备,显示该设备当前运行的ID和硬盘中存在的程序清单,当点击某一条任务清单,再显示该程序在设备中运行的真实时间。
而且单条程序的默认查询时间是,以当前时间为结束时间,查询一个月的数据量。
where条件就好判断了,首先,设备ID,程序名PName,时间。
不多说,组合索引造一个。
ALTER TABLE BU_Machine_Program_History ADD INDEX idx_Mac_ID_PName_AddTimeStamp(Mac_ID, PName, AddTimeStamp);
BU_Machine_Params_History
该表存放着程序的循环时间。
select count(1) from BU_Machine_Params_History; – 4829574
后端API
获取程序列表(当前正在运行的程序,历史程序列表)
BuStatusListController.java
/**
* 根据机器ID查询历史程序列表
*/
@GetMapping("/getPNameList/{macId}")
public AjaxResult getPNameList(@PathVariable(value = "macId") Integer macId){
List<Map<String, Object>> pNameList = statusListService.getPNameListByMacId(macId);
return AjaxResult.success(pNameList);
}
BuStatusListServiceImpl.java
@Override
public List<Map<String, Object>> getPNameListByMacId(Integer macId) {
Map<String, Object> result = new HashMap<>();
result.put("current",machineProgramHistoryMapper.selectCurrentPNumByMacId(macId));
result.put("history",machineProgramHistoryMapper.selectPNumListByMacId(macId));
List<Map<String, Object>> list = new ArrayList();
list.add(result);
return list;
}
Mapper.xml
<select id="selectPNumListByMacId" parameterType="Long" resultType="Map">
select a.PNum,a.PName,a.PSize from BU_Machine_CurrProgramList a
<where>
<if test="macId != null "> and a.Mac_ID = #{macId}</if>
and a.IsDel = 0
</where>
</select>
<select id="selectCurrentPNumByMacId" parameterType="Long" resultType="Map">
select PNum,PName,PSize from BU_Machine_CurrProgram
<where>
<if test="macId != null "> and Mac_ID = #{macId}</if>
and IsDel = 0
</where>
</select>
上面的语句,查询的是设备下的程序列表。
点击某个程序,查询它的循环时间。
BuStatusListController.java
/**
* 根据机器ID和程序名PName查询循环时间列表
*/
@GetMapping("/getCycleTimeList")
public AjaxResult getCycleTimeList(@RequestParam Map<String, Object> params){
List<Map<String, Object>> cycleTimeList = statusListService.getCycleTimeListByMap(params);
return AjaxResult.success(cycleTimeList);
}
BuStatusListServiceImpl.java
@Override
public List<Map<String, Object>> getCycleTimeListByMap(Map<String, Object> params) {
return machineProgramHistoryMapper.selectCycleTimeListByMap(params);
}
Mapper.xml
<resultMap id="programHistoryMap" type="java.util.HashMap">
<result property="addTimeStamp" column="AddTimeStamp" />
<result property="cycleTime" column="CycleTime" />
</resultMap>
<select id="selectCycleTimeListByMap" parameterType="Map" resultMap="programHistoryMap">
SELECT AddTimeStamp,CycleTime FROM( SELECT a.AddTimeStamp,
IFNULL(b.CycleTime,0) as CycleTime
FROM BU_Machine_Program_History a LEFT JOIN BU_Machine_Params_History b ON a.Mac_ID = b.Mac_ID
AND a.AddTimeStamp = b.AddTimeStamp
<where>
<if test="macId != null "> and a.Mac_ID = #{macId}</if>
<if test="pName != null and pName != ''"> and a.PName = #{pName}</if>
AND a.AddTimeStamp > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 MONTH))*1000
</where>
) c WHERE c.CycleTime > 0
</select>
我做了过滤,如果循环时间为0的记录,剔除不用,这样有效记录数大概在100条以内,而不是原始的数十万条。