产品需求:
按照天统计策略信收信人数和收信次数。以前策略信只有发送是没有收集的,现在要数据咋办,得收集啊。
设计方案:
因为策略信的发送是在一个单独的工程里,没有连接数据库。于是收集策略信放到了redis的list里,其中redis的key按照当天日期标识,因为还要统计收策略信的次数,所以允许重复,选择了redis的list。
然后在管理后台的工程里,通过定时任务取redis的数据,存到表里。
数据统计,直接查询表数据。
结果:
数据是正确的,没问题。但是跑了一段时间后,发现这个表的数据太大了。。。。。。
重新设计方案:
删除历史数据,仅保留最近3个月的。但是这个表定时插入、定时查询、定时删除,可能会把数据库搞垮了。
那就搞个新的表, 执行定时插入和定时查询,老的表执行定时删除。问题来了:搞一个新的表,跑一段时间,不还是会数据太大吗?弄一个分表,10天1张表。
1. 先看mybatis如何创建表
<select id="existTable" parameterType="String" resultType="Integer">select count(*)from information_schema.TABLESwhere table_name = #{tableName}</select><!-- 删除指定的表--><update id="dropTable">DROP TABLE IF EXISTS ${tableName}</update><!-- 创建新的日志表--><update id="createTable" parameterType="String">CREATE TABLE ${tableName}(`id` bigint(20) NOT NULL AUTO_INCREMENT,`day` varchar(45) DEFAULT NULL COMMENT '日期',`userid` bigint(20) DEFAULT NULL COMMENT '用户id',`country` varchar(45) DEFAULT NULL COMMENT '国家',`channel` varchar(45) DEFAULT NULL COMMENT '渠道',`af_channel` varchar(64) DEFAULT NULL COMMENT '归因渠道',`user_regist_time` datetime DEFAULT NULL COMMENT '用户注册时间',`create_time` datetime DEFAULT NULL COMMENT '创建时间',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT;</update>
2. 如何做到10天分表
String tableCacheKey = "day:strategy:buried:tablename";String tableName = "day_strategy_buried_";DateTime todayDateTime = DateTime.now();String tableDateNumber = todayDateTime.toString("yyyyMMdd");if(!redisUtil.hasKey(tableCacheKey)) { //redis里没有,就用当天日期tableName += tableDateNumber;redisUtil.set(tableCacheKey,todayDateTime.toString("yyyy-MM-dd"),30, TimeUnit.DAYS);} else {Object tableDateFromRedis = redisUtil.get(tableCacheKey);DateTime redisDateTime = DateTime.parse(tableDateFromRedis.toString());int daysBetween = Days.daysBetween(redisDateTime,todayDateTime).getDays();if (daysBetween % 10 != 0) {//不够10天就用上一次存的日期,tableDateNumber = redisDateTime.toString("yyyyMMdd");} else {//够10天就用新的日期redisUtil.set(tableCacheKey,todayDateTime.toString("yyyy-MM-dd"),30, TimeUnit.DAYS);}tableName += tableDateNumber;}log.info("tableName................{}",tableName);//判断表是否存在int exist = strategyBuriedMapper.existTable(tableName);if (exist > 0) return tableName;//不存在,则创建strategyBuriedMapper.createTable(tableName);
运行几天,看看啥效果。
有好的方案,欢迎赐教。