首页 > 数据库 >Spring Boot 中 PGSQL 判断打卡点是否经过轨迹优化代码,循环查询物理表修改生成临时表,向临时表插入数据后再做ST_DWithin判断

Spring Boot 中 PGSQL 判断打卡点是否经过轨迹优化代码,循环查询物理表修改生成临时表,向临时表插入数据后再做ST_DWithin判断

时间:2024-07-02 20:56:47浏览次数:19  
标签:info temp 临时 car ST trajectory import 打卡

记录一下一个业务问题,流程是这样的,我现在有一个定时任务,5分钟执行一次,更新车辆打卡的情况。现在有20俩车,每辆车都分配了路线,每条路线都有打卡点,每个打卡点分配了不同的时间段,也就是说,一条路线可能有几百个打卡点,这几百个打卡点中每一个都分配了时间段,有可能是1个时间段,比如8:00 - 10:00这个时间段,要去打卡。也有可能有的打卡点分配了几个时间段,比如上午两个时间段,下午两个时间段。这个时候要去判断今天的打卡情况,只能先获取路线的打卡点,然后再获取单个打卡点下面的时间段,再进行判断操作。但是问题来了,之前的写法for循环去判断只针对少数打卡点,比如一条路线也就5 - 10个打卡点这样。但是现在打卡点数量过多,路线增加,以及每个打卡点都有打卡时间段,for循环操作数据库判断无比的慢,以及非常的消耗资源内存等。。但是判断是否经过打卡点这种必须要在sql里面执行判断,之所有必须在sql判断,因为pgsql提供的ST_DWithin函数就是判断是否在缓冲区范围经过打卡点的。。所以离不开sql判断。下面代码是for循环的操作,先循环出单条路线的打卡点,然后再根据打卡点的ID用stream流匹配打卡点的时间段,再循环每个时间段到sql里面进行判断。

在这里插入图片描述

sql语句判断是这样的

在这里插入图片描述

既然我们离不开sql语句判断,那就只能按照老套路,加索引这些。但是加索引提升了一点查询速度,持续的查询非常的消耗内存,导致项目运行的时候内存持续的猛增。一天时间涨了2G多,这明显很离谱。。。即使GC了,内存也无法得到释放。

在这里插入图片描述

咨询了部门里的老大哥,我问他我这种打卡点判断,能不能不走sql,他说不行的,这种必须走sql的,必须走pg的ST_DWithin函数判断。他给了我一个解决方案,让我先获取出当天的轨迹数据,也就是car_trajectory_info物理表的当天数据,每次定时任务执行的时候,先查出当天的轨迹数据,然后创建临时表,把当天的轨迹数据放到临时表里面,然后把之前的sql判断语句只查临时表,比如创建了一个临时表car_trajectory_info_temp,把原来的sql语句的物理表car_trajectory_info改成car_trajectory_info_temp,执行判断结束后在把临时表删除掉。这样下来,就不会走物理表了,直接走临时表做查询(这里记得在创建临时表的时候加上索引)

具体实现临时表操作如下:

测试类

package com.yutu.garden.task;

import cn.hutool.core.collection.CollUtil;
import com.yutu.garden.entity.CarTrajectoryInfo;
import com.yutu.garden.mapper.gardens.CarTrajectoryInfoMapper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Component
@EnableScheduling
public class ScheduledTasks01 {

	@Resource
	private CarTrajectoryInfoMapper carTrajectoryInfoMapper;

    // 第一个定时任务,每隔5秒执行一次
    @Async("taskExecutor")
    @Scheduled(cron = "*/10 * * * * *")
    @Transactional
    public void task() {

		//先查询出当天的轨迹数据,按照条件吧,如果还有条件,可以更加详细到某些指定的数据,比如说按车牌号条件筛选
		List<CarTrajectoryInfo> carTrajectoryInfoList = carTrajectoryInfoMapper.getToDayCarInfoList();

		//测试 创建临时表
		carTrajectoryInfoMapper.createTempTable();
		System.out.println("临时表创建成功");

		//递归向临时表中插入当天的数据(防止数据量过大引发IO异常)
		add(carTrajectoryInfoList,0L,500L);

        //查询临时表(在这里判断是否经过打卡点!)
        CarTrajectoryInfo carTrajectoryInfo = carTrajectoryInfoMapper.selectTempTable(必要的参数,这里只是测试);
		System.out.println("执行查询,如果为空,那就是没有经过打卡点,如果不为空那就是已经经过打卡点");
        System.out.println(carTrajectoryInfo);

		System.out.println("删除临时表");
		carTrajectoryInfoMapper.dropTempTable();

    }


	//递归插入(防止数据量过大引发IO异常)
	public void add (List<CarTrajectoryInfo> all,long start,long limit){
		//截取 从start开始截取 截取limit条
		List<CarTrajectoryInfo> collect = all.stream().skip(start).limit(limit).collect(Collectors.toList());
		if(CollUtil.isEmpty(collect)){
			return;
		}
		//批量插入数据的方法
		//保存车辆轨迹数据
		carTrajectoryInfoMapper.insertDataTempTable(collect);
		//递归 每次插入limit条数据
		add(all,start+limit,limit);
	}

}

mapper层

package com.yutu.garden.mapper.gardens;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.yutu.garden.entity.CarTrajectoryInfo;
import com.yutu.garden.vo.CarWarnInfoCqZtVo;
import com.yutu.garden.vo.CarWarnInfoZyInfoVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;

import java.time.LocalDate;
import java.util.Date;
import java.util.List;


@Mapper
public interface CarTrajectoryInfoMapper extends BaseMapper<CarTrajectoryInfo> {

	//获取当天轨迹数据
	List<CarTrajectoryInfo> getToDayCarInfoList();

	//批量插入数据
	void insertDataTempTable(@Param("carTrajectoryInfoList") List<CarTrajectoryInfo> carTrajectoryInfoList);

	//创建临时表
	void createTempTable();

	//使用临时表执行判断
	CarTrajectoryInfo selectTempTable(@Param("geom")String geom,
									  @Param("sRid")Integer sRid,
									  @Param("carNo")String carNo,
									  @Param("radius") Integer radius,
									  @Param("startTime") String startTime,
									  @Param("endTime") String endTime);

	//删除临时表
	void dropTempTable();

}

xml中sql语句

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yutu.garden.mapper.gardens.CarTrajectoryInfoMapper">


    <select id="getToDayCarInfoList" resultType="com.yutu.garden.entity.CarTrajectoryInfo">
        select * from car_trajectory_info where DATE(upload_time) = CURRENT_DATE
    </select>


    <sql id="createTempTableSQL">
        CREATE TEMPORARY TABLE car_trajectory_info_temp (
          id int8 NOT NULL,
          car_no varchar(255),
          device_no varchar(255),
          lng float8,
          lat float8,
          speed float8,
          upload_time timestamp(6),
          distance float8,
          duration float8,
          today_distance float8,
          geom geometry,
          clean_area float8
        );
        CREATE INDEX car_trajectory_info_temp_car_no_idx ON car_trajectory_info_temp USING btree (car_no);
        CREATE UNIQUE INDEX car_trajectory_info_temp_id_uindex ON car_trajectory_info_temp USING btree (id);
        CREATE INDEX car_trajectory_info_temp_upload_time_idx ON car_trajectory_info_temp USING btree (upload_time);
        CREATE INDEX car_trajectory_info_temp_geom_idx ON car_trajectory_info_temp USING gist (geom);
    </sql>

    <update id="createTempTable">
        <include refid="createTempTableSQL"/>
    </update>

    <insert id="insertDataTempTable">
        INSERT INTO car_trajectory_info_temp
        (id,car_no, device_no, lng, lat, speed, upload_time, distance, duration, today_distance, geom, clean_area)
        VALUES
        <foreach collection="carTrajectoryInfoList" item="item" separator=",">
            (
            #{item.id},
            #{item.carNo},
            #{item.deviceNo},
            #{item.lng},
            #{item.lat},
            #{item.speed},
            #{item.uploadTime},
            #{item.distance},
            #{item.duration},
            #{item.todayDistance},
            st_geomfromtext(st_astext(#{item.geom}), 4326),
            #{item.cleanArea}
            )
        </foreach>
    </insert>

    <select id="selectTempTable" resultType="com.yutu.garden.entity.CarTrajectoryInfo">
        select
        id,upload_time,car_no
        from
        car_trajectory_info_temp
        where
        0=0
        <if test="geom != null and geom != ''">
            and ST_DWithin(geom, st_geomfromtext(st_astext(#{geom}), #{sRid}), #{radius},false)
        </if>
        <if test="carNo != null and carNo != ''">
            and car_no = #{carNo}
        </if>
        <if test="startTime != null and startTime != ''">
            and to_char(upload_time, 'HH24:MI:SS') &gt;= #{startTime}
        </if>
        <if test="endTime != null and endTime != ''">
            and to_char(upload_time, 'HH24:MI:SS') &lt;= #{endTime}
        </if>
        limit 1
    </select>

    <sql id="dropTempTableSQL">
        DROP TABLE IF EXISTS car_trajectory_info_temp;
    </sql>
    <update id="dropTempTable">
        <include refid="dropTempTableSQL"/>
    </update>

</mapper>

标签:info,temp,临时,car,ST,trajectory,import,打卡
From: https://blog.csdn.net/weixin_44912902/article/details/140135104

相关文章

  • Elasticsearch集群部署(上)
    目录前言一.环境准备二.实施部署三. 安装配置head监控插件(只在第一台es部署)四.Kibana部署(当前还是在第一台es部署)五. 安装配置Nginx反向代理六. Logstash部署与测试前言1.Elasticsearch:  是一个基于Lucene的搜索服务器。提供搜集、分析、存储数据三大......
  • python系列&deep_study系列:python如何将语音转文字
    python如何将语音转文字python如何将语音转文字在本文中,我们将探讨解决此问题的三种不同方法。方法1:使用SpeechRecognition库方法2:使用GoogleCloudSpeech-to-TextAPI方法3:使用PyAudio库python如何将语音转文字如果在python中将语音转换成文本?在本文......
  • python系列&deep_study系列:Whisper——部署fast-whisper中文语音识别模型
    Whisper——部署fast-whisper中文语音识别模型Whisper——部署fast-whisper中文语音识别模型环境配置准备tiny模型模型转换代码Whisper——部署fast-whisper中文语音识别模型whisper:https://github.com/openai/whisper/tree/main参考文章:WhisperOpenAI开源语音......
  • 【0299】Postgres内核之哈希表(Hash Tables)
    0.哈希表(HashTables)哈希表是一种用于存储键值对的数据结构。与使用索引号访问元素的基本数组不同,哈希表使用键来查找表条目。这使得数据管理对于用户来说更易于管理,因为按属性对数据条目进行分类比按它们在一个巨大的列表中的数量更容易。在C++中,我们将哈希表实现为......
  • logstash 收集 http POST请求中的json日志时,字段冲突问题
    https://www.elastic.co/guide/en/logstash/current/plugins-inputs-http.html修改vim/etc/logstash/logstash.ymlpipeline.ecs_compatibility:disabled不关闭的话,会自动添加这几个字段可能会与json中的同名字段冲突{"@version"=>"1","user_agent"......
  • 【嵌入式DIY实例】- LCD ST7735显示DHT11传感器数据
    LCDST7735显示DHT11传感器数据文章目录LCDST7735显示DHT11传感器数据1、硬件准备与接线2、代码实现本文介绍如何将ESP8266NodeMCU板(ESP-12E)与DHT11(RHT01)数字湿度和温度传感器连接。NodeMCU从DHT11传感器读取温度(以°C为单位)和湿度(以r......
  • Python TensorFlow双向Bi-LSTM长短期记忆神经网络深度学习可视化用户传感器活动数据
    全文链接:https://tecdat.cn/?p=36613原文出处:拓端数据部落公众号在本文中,我们旨在利用深度学习技术,特别是TensorFlow框架下的Keras库,对WISDM(无线传感器数据挖掘)数据集进行活动识别。WISDM数据集包含了从用户身上佩戴的加速度传感器收集的三轴加速度数据,这些数据被用于识别用户的......
  • 基于springboot用“异常处理器“捕获解决“数据库信息录入重复“的问题“SQLIntegrity
    前言 当我们编写后端时,会遇到一个问题,那就是:假如A用户向我们的数据库录入完登录信息后(姓名,账号等),B用户同样采用了一个相同的姓名提交了登录信息,那这个时候就不满足username的唯一约束,此时数据库就会报错例如报错如下:Duplicateentry'····'forkey'····'提示......
  • String.format 日期占位 去除左侧的填充0
    原文链接: https://baijiahao.baidu.com/s?id=1764834107971798887&wfr=spider&for=pc假设我们要输出当前的日期时间,我们可以使用如下代码:Datedate=newDate();System.out.println("输出结果:"+String.format("%tF%tT",date,date));输出结果为:输出结果:2023-......
  • .Net Core 链接postgresql 数据库
    安装依赖包Npgsql.EntityFrameworkCore.PostgreSQL必须Npgsql.EntityFrameworkCore.PostgreSQL.Design数据迁移相关新建数据库上下文类AppDbContext.cs注意当前文件,所在的项目,必须安装上面的依赖包//命名空间namespaceService{///<summary>///继承......