数据汇总从20s优化至2s(小经验)

目录

项目背景:

数据汇总访问时间长的问题:

解决方案:

1.创建参与访问表

2.使用redis进行优化

总结:


项目背景:

        一个简单的抽奖系统,当要统计每天的参与访问,总的参与访问

数据汇总访问时间长的问题:

        每次访问都会遍历整个订单表进行查询,当数据库数据多的时候会对数据库造成压力,也会更加耗时,初始查询20秒

解决方案:

        新建一张数据汇总表,例如拿总参与,总访问,每日参与,每日访问来说,遍历订单表查询是不太合理的,会占用大量的系统资源,可以利用redis的缓存递增来做,将一些数据临时放入redis里面,数据汇总的时候在持久化到mysql数据库中

1.创建参与访问表

sql语句:

CREATE TABLE `sb_access_count` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `created` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `access_count` int DEFAULT NULL COMMENT '当日访问量',
  `user_count` int NOT NULL DEFAULT '0' COMMENT '当天参与量',
  `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci ROW_FORMAT=DYNAMIC;

① 创建参与访问表,作为日数据的保存,每次访问我们的接口都在这个表里面累加1

         但是每次访问我们的接口,都会对数据库造成吃就会,也会对数据库造成压力,不合理,这里我们可以用redis进行优化

2.使用redis进行优化

①将每日参与访问保存至redis

        定义一个固定的Key加上当日的时间作为redis的key,value的值为每日的参与和访问,第一次访问的时候先查询一下看redis里面是否有值,没有的话就是存进去,然后是1,如果有值就redis缓存递增1

    public void activityDayAccessCount(String itemCode) {
        ActivityDO activityDO = activityDao.getActivityByCode(itemCode);
        if (activityDO == null) {
            logger.info("增加每日访问数量,查询不到该活动= " + itemCode);
            return;
        }
        RedisUtils redisUtils = MyApplicationContext.getBean(RedisUtils.class);
        Date date = new Date();
        String time = DateUtils.datePathyyyymmdd(date);
        //活动访问key
        String accessesKey = itemCode + MyConstant.DAY_ACCESSES + time;
        Integer sum = (Integer) redisUtils.get(accessesKey);
        if (sum == null) {
            int expireTime = 2 * 24 * 60 * 60;
            redisUtils.set(accessesKey, 1, expireTime);
        } else {
            //缓存递增
            redisUtils.incr(accessesKey, 1);
        }
    }

②持久化到数据库

有两种情况下会持久化到数据库

        第一种:写一个定时任务,每天定时持久化到数据库

        第二种:点击数据汇总的时候调用此方法,将redis最新的数据拉取到本地,在进行数据汇总

    public void task() {
        logger.info("参与访问数据落库========>");
        Date date = new Date();
        String time = DateUtils.datePathyyyymmdd(date);
        String acessKey = MyConstant.ACCESS_SUM_KEY + time;
        String userCanyuKey = MyConstant.PARTICIPAT_SUM_KEY + time;
        System.out.println("acessKey = " + acessKey);
        System.out.println("userCanyuKey = " + userCanyuKey);
        Integer accessCount = (Integer) redisUtils.get(acessKey);
        System.out.println("accessCount = " + accessCount);
        Integer userCount = (Integer) redisUtils.get(userCanyuKey);
        System.out.println("userCount = " + userCount);
        Date dayStart = DateUtils.getDayStart(date);
        Date dayEnd = DateUtils.getDayEnd(date);

        QueryWrapper<AccessCountDO> queryWrapper = new QueryWrapper();
        queryWrapper.ge("created", dayStart);
        queryWrapper.le("created", dayEnd);
        AccessCountDO accessCountDO = accessCountMapper.selectOne(queryWrapper.orderByDesc("id").last("limit 1"));
        if (accessCountDO == null) {
            accessCountDO = new AccessCountDO();
            if (accessCount == null) {
                accessCountDO.setAccessCount(0);
            } else {
                accessCountDO.setAccessCount(accessCount);
            }
            if (userCount == null) {
                accessCountDO.setUserCount(0);
            } else {
                accessCountDO.setUserCount(userCount);
            }
            accessCountMapper.insert(accessCountDO);
        } else {
            accessCountDO.setAccessCount(accessCount);
            accessCountDO.setUserCount(userCount);
            accessCountMapper.updateById(accessCountDO);
        }
}

        以上方法不用每次都查询订单表,尤其是订单表数据量过大的时候会很耗时,给用户造成不好的体验

总结:

        需要善用redis,redis作为缓存数据库性能非常高,尽量不要与mysql数据库进行交互,把一些非实时的数据缓存至redis,查询效率非常高!

猜你喜欢

转载自blog.csdn.net/m0_58709145/article/details/130526475