这是对之前做的一篇文章的优化——后端——Java Stream流多字段分组 业务层实现sql的分组聚合功能。拿到需求的第一时间就想到在业务层进行聚合操作,但是后面发现实在是太慢了,统计数据得5分钟,后面优化了之后可以不到5秒钟完成统计。(数据量:400w)

优化分析

在业务层使用stream流实现聚合操作,没有充分利用taos数据库的聚合函数,在数据库层对40w数据做聚合操作只需要不到1s。

优化步骤:

  • 根据分组条件,使用taos聚合操作在持久层进行聚合操作

  • 在根据分组条件去找其他字段(一条记录即可)

直接上代码

service

@Service
@Slf4j
public class TaosServiceImpl implements TaosService {
​
    @Autowired
    private TaosMapper taosMapper;
​
    /**
     * 根据时间区间统计实时数据
     * @param startTime
     * @param endTime
     * @return
     */
    /*
        业务层实现以下sql
        SELECT COUNT(id) weldDuration,weldModel,gatherNo,welderNo,weldStatus,machineId,machineNo,
        machineDeptId,gatherId,gatherDeptId,welderId,welderName,welderDeptId,taskId,taskName,taskNo,SYSDATE(),
        '${startTime}','${endTime}',AVG(electricity),AVG(voltage),AVG(wireFeedRate),AVG(wireDiameter),AVG(wireMaterialsGases),
        AVG(gasesFlow),walkSpeed
        FROM `base_cloud_weldmes_rtdata`.${tableName}
        WHERE weldTime BETWEEN #{startTime} AND #{endTime}
        GROUP BY gatherNo, weldStatus, welderNo
     */
    @Override
    public List<OtcV2RtDataDb> getWeldStatisticsData(String startTime, String endTime) {
​
        List<OtcV2RtDataDb> totalStatisticsData = new ArrayList<>();
​
        // 查询数据中的表明
        List<String> tables = taosMapper.showTables();
​
        // 根据表名和时间区间查询实时数据
        for (String table : tables) {
​
            // 先查询统计数据的聚合数据
            List<OtcV2RtDataDb> statisticsData = taosMapper.getStatisticsData(startTime, endTime, table);
            // 再查询统计数据的其他字段
            statisticsData.forEach(temp -> {
                OtcV2RtDataDb otherColumn = taosMapper.getStatisticsDataOtherColumn(table, temp.getGatherNo(), temp.getWeldStatus(), temp.getWelderNo());
                setOtherColumn(otherColumn, temp);
            });
​
            totalStatisticsData.addAll(statisticsData);
        }
​
​
        return totalStatisticsData;
    }
​
    private void setOtherColumn(OtcV2RtDataDb source, OtcV2RtDataDb target) {
        target.setWeldModel(source.getWeldModel());
        target.setMachineId(source.getMachineId());
        target.setMachineNo(source.getMachineNo());
        target.setMachineDeptId(source.getMachineDeptId());
        target.setGatherId(source.getGatherId());
        target.setGatherDeptId(source.getGatherDeptId());
        target.setWelderId(source.getWelderId());
        target.setWelderName(source.getWelderName());
        target.setWelderDeptId(source.getWelderDeptId());
        target.setTaskId(source.getTaskId());
        target.setTaskName(source.getTaskName());
        target.setTaskNo(source.getTaskNo());
    }
}
​

mapper.xml

<select id="getStatisticsData" resultMap="TdInsertDTOResult">
    SELECT gatherNo, weldStatus, welderNo,
           '#{startTime}' startTime,
           '#{endTime}' endTime,
           COUNT(ts) weldDuration,
           AVG(electricity) electricity,
           AVG(voltage) voltage,
           AVG(wireFeedRate) wireFeedRate,
           AVG(wireDiameter) wireDiameter,
           AVG(wireMaterialsGases) wireMaterialsGases,
           AVG(gasesFlow) gasesFlow
    FROM #{tableName} WHERE weldTime BETWEEN #{startTime} AND #{endTime}
    GROUP BY gatherNo, weldStatus, welderNo
</select>
​
<select id="getStatisticsDataOtherColumn" resultMap="TdInsertDTOResult">
    SELECT *
    FROM #{tableName}
    WHERE gatherNo = #{gatherNo} and weldStatus = #{weldStatus} and welderNo = #{welderNo} limit 1;
</select>

对于同一个需求,这样真的快了不少,代码也少了不少,天,之前怎么没想到!前面一篇文章就当对stream流groupingBy的学习了

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐