feat(record): 添加物联网数据采样查询功能

- 在 RecordIotenvInstant 模型中添加 samplingInterval 字段
- 在 RecordIotenvInstantMapper 中添加采样查询方法
- 在 RecordIotenvInstantServiceImpl 中实现采样查询逻辑
- 通过分段+聚合的方式提高查询性能,适用于大量数据场景
boardTest
zch 4 weeks ago
parent f2d9c3dc16
commit 10defcc6a7

@ -90,6 +90,8 @@ public class RecordIotenvInstant extends BaseEntity
private Long monitorType;
private String energyName;
/** 采样间隔(分钟),用于数据抽稀 */
private Integer samplingInterval;
//
// public void setObjid(Long objid)

@ -154,4 +154,15 @@ public interface RecordIotenvInstantMapper
*/
public List<RecordIotenvInstant> selectLatestRecordsByMonitorIdsFromTable(@Param("tableName") String tableName,
@Param("monitorIds") List<String> monitorIds);
/**
*
*
*
* @param tableNames
* @param recordIotenvInstant samplingInterval
* @return
*/
List<RecordIotenvInstant> selectRecordIotenvInstantListFromTablesWithSampling(@Param("tableNames") List<String> tableNames,
@Param("recordIotenvInstant") RecordIotenvInstant recordIotenvInstant);
}

@ -72,8 +72,15 @@ public class RecordIotenvInstantServiceImpl implements IRecordIotenvInstantServi
if (tableNames.isEmpty()) {
return new ArrayList<>();
}
// 执行分表查询
return recordIotenvInstantMapper.selectRecordIotenvInstantListFromTables(tableNames, recordIotenvInstant);
// 检查是否需要采样
if (recordIotenvInstant.getSamplingInterval() != null && recordIotenvInstant.getSamplingInterval() > 1) {
// 使用采样查询
return recordIotenvInstantMapper.selectRecordIotenvInstantListFromTablesWithSampling(tableNames, recordIotenvInstant);
} else {
// 使用普通查询
return recordIotenvInstantMapper.selectRecordIotenvInstantListFromTables(tableNames, recordIotenvInstant);
}
}
/**

@ -366,4 +366,43 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
) t2 ON t1.monitorId = t2.monitorId AND t1.objid = t2.max_objid
</select>
<!-- 高性能采样查询TiDB原生优化无索引依赖 -->
<select id="selectRecordIotenvInstantListFromTablesWithSampling" resultMap="RecordIotenvInstantResult">
<!-- 使用分段+聚合的高效算法,避免复杂窗口函数 -->
<foreach collection="tableNames" item="tableName" separator=" UNION ALL ">
SELECT
t1.objid, t1.monitorId, t1.temperature, t1.humidity, t1.illuminance, t1.noise, t1.concentration,
t1.vibration_speed, t1.vibration_displacement, t1.vibration_acceleration, t1.vibration_temp,
t1.collectTime, t1.recodeTime
FROM ${tableName} t1
INNER JOIN (
SELECT
monitorId,
FLOOR(UNIX_TIMESTAMP(recodeTime) / (#{recordIotenvInstant.samplingInterval} * 60)) as time_slot,
MAX(recodeTime) as max_time
FROM ${tableName}
<where>
<if test="recordIotenvInstant.monitorId != null and recordIotenvInstant.monitorId != ''">
AND monitorId = #{recordIotenvInstant.monitorId}
</if>
<if test="recordIotenvInstant.params.beginRecordTime != null and recordIotenvInstant.params.endRecordTime != null">
AND recodeTime &gt;= #{recordIotenvInstant.params.beginRecordTime}
AND recodeTime &lt;= #{recordIotenvInstant.params.endRecordTime}
</if>
<if test="recordIotenvInstant.monitorIds != null and recordIotenvInstant.monitorIds.length > 0">
AND monitorId IN
<foreach collection="recordIotenvInstant.monitorIds" item="monitorId" open="(" separator="," close=")">
#{monitorId}
</foreach>
</if>
AND (temperature IS NULL OR temperature BETWEEN 0 AND 80)
AND (humidity IS NULL OR humidity BETWEEN 0 AND 80)
AND (noise IS NULL OR noise BETWEEN 0 AND 80)
</where>
GROUP BY monitorId, time_slot
) t2 ON t1.monitorId = t2.monitorId AND t1.recodeTime = t2.max_time
</foreach>
ORDER BY monitorId ASC, recodeTime ASC
</select>
</mapper>
Loading…
Cancel
Save