产品需求:
按照天统计策略信收信人数和收信次数。以前策略信只有发送是没有收集的,现在要数据咋办,得收集啊。
设计方案:
因为策略信的发送是在一个单独的工程里,没有连接数据库。于是收集策略信放到了redis的list里,其中redis的key按照当天日期标识,因为还要统计收策略信的次数,所以允许重复,选择了redis的list。
然后在管理后台的工程里,通过定时任务取redis的数据,存到表里。
数据统计,直接查询表数据。
结果:
数据是正确的,没问题。但是跑了一段时间后,发现这个表的数据太大了。。。。。。
重新设计方案:
删除历史数据,仅保留最近3个月的。但是这个表定时插入、定时查询、定时删除,可能会把数据库搞垮了。
那就搞个新的表, 执行定时插入和定时查询,老的表执行定时删除。问题来了:搞一个新的表,跑一段时间,不还是会数据太大吗?弄一个分表,10天1张表。
1. 先看mybatis如何创建表
<select id="existTable" parameterType="String" resultType="Integer">
select count(*)
from information_schema.TABLES
where 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);
运行几天,看看啥效果。
有好的方案,欢迎赐教。