当业务运行一段时间后,会出现有些表数据量很大,可能对系统性能产生不良的影响,常见的如订单表、登录log表等,这些数据很有时效性,比如我们一般很少去查上个月的订单,最多也就是报表统计会涉及到。

解决方案:创建一个存储过程,每月定时调用,查出上个月数据保存到新建的表中,新表命名以月份为后缀,删除主表中上个月数据。

存储过程

CREATE OR REPLACE
procedure operate_log_proc(return_code OUT VARCHAR2,return_msg  OUT VARCHAR2)
authid current_user
iserr_index           NUMBER;log_table_name      VARCHAR2(20);current_month_start DATE;create_table_cursor NUMBER(10);create_table_sql    VARCHAR2(1000);insert_data_sql     VARCHAR2(1000);delete_data_sql     VARCHAR2(1000);v_count                      NUMBER(10);
beginreturn_msg  := '执行[OPERATE_LOG_PROC]成功';return_code := '1';err_index := 1;-- 生成分表的表名SELECT 'Operate_Log_' ||TO_CHAR(ADD_MONTHS(TRUNC(SYSDATE, 'MM'), -1), 'yyyymm')INTO log_table_nameFROM DUAL;--表存在不用创建select count(1) into v_count from user_tables where table_name = log_table_name;if v_count <= 0 THEN-- 打开游标create_table_cursor := DBMS_SQL.OPEN_CURSOR;-- 拼接创建表的SQL语句,并执行create_table_sql := 'CREATE TABLE "' || log_table_name || '" ("Num_ID" NUMBER(32) NOT NULL ,"Reg_ID" CHAR(12 BYTE) NOT NULL ,"User_ID" CHAR(18 BYTE) NOT NULL ,"Organization" VARCHAR2(100 BYTE) NOT NULL ,"Organization_ID" CHAR(12 BYTE) NOT NULL ,"User_Name" VARCHAR2(30 BYTE) NOT NULL ,"Operate_Time" CHAR(14 BYTE) NOT NULL ,"Terminal_ID" VARCHAR2(40 BYTE) NOT NULL ,"Operate_Type" NUMBER(1) NOT NULL ,"Operate_Result" CHAR(1 BYTE) NOT NULL ,"Error_Code" CHAR(4 BYTE) NULL ,"Operate_Name" VARCHAR2(30 BYTE) NOT NULL ,"Operate_Condition" VARCHAR2(200 BYTE) NOT NULL ,"Insert_Time" DATE NOT NULL ,"Foreign_Reg_ID" VARCHAR2(36 BYTE) NOT NULL ,"Operate_Display" VARCHAR2(2000 BYTE) NULL)';DBMS_SQL.PARSE(create_table_cursor, create_table_sql, DBMS_SQL.V7);DBMS_SQL.CLOSE_CURSOR(create_table_cursor);end if; err_index := 2;-- 当前月起始时间,如2019-09-01 00:00:00SELECT TRUNC(SYSDATE, 'MM') INTO current_month_start FROM DUAL;-- 将Operate_Log表中上月记录添加到新创建的表中insert_data_sql := 'INSERT INTO "' || log_table_name ||'" (SELECT * FROM "Operate_Log" WHERE to_char("Insert_Time", ''YYYY-MM-DD'') < to_char(to_date(''' ||current_month_start || ''',''YYYY-MM-DD''), ''YYYY-MM-DD''))';EXECUTE IMMEDIATE insert_data_sql;err_index := 3;-- 从Operate_Log表中删除上月记录delete_data_sql := 'DELETE FROM "Operate_Log" WHERE to_char("Insert_Time", ''YYYY-MM-DD'') < to_char(to_date(''' ||current_month_start || ''',''YYYY-MM-DD''), ''YYYY-MM-DD'')';EXECUTE IMMEDIATE delete_data_sql;err_index := 4;COMMIT;EXCEPTIONWHEN OTHERS THENreturn_msg  := '过程[OPERATE_LOG_PROC]出错,' || '第[' || err_index ||']块语句出错';return_code := '0';ROLLBACK;end operate_log_proc;

说明:operate_log_proc存储过程名称,Operate_Log表名。authid current_user关键字给存储过程授权,不然报错找不到表。

定时任务

BEGINdbms_scheduler.create_job(job_name        => 'my_job_test',   --定时任务名称job_type        => 'STORED_PROCEDURE',    --类型存储过程job_action      => 'declare return_code VARCHAR2(200);return_msg VARCHAR2(200);begin OPERATE_LOG_PROC(return_code,return_msg); end;', --存储过程名称start_date      => sysdate, --立刻执行repeat_interval => 'TRUNC(LAST_DAY(SYSDATE))+1+5/24',    -- 每月1号5点执行enabled         => TRUE,  --是否启用comments        => 'test'); --备注end;

说明:没有参数的存储过程,可以直接用存储过程名称加上";"分号。需要权限才能创建。

分割线


如果不想用存储过程,也可以用代码的方式实现,使用Spring Boot + Mybatis + Oracle 实现。

思路:使用scheduling定时任务,每天定时触发,动态创建新表,备份历史数据。

关键代码:

SysLogService.java

/*** 系统日志接口*/
public interface SysLogService {/*** 备份日志* @param createTime   时间* @param timeSuffix  后缀*/void backupLog(String createTime, String timeSuffix);/*** 表是否存在* @param tableName  表名* @return    true存在,false不存在*/boolean existTable(String tableName);/*** 创建表* @param tableName    表名*/void createTable(String tableName);
}

SysLogServiceImpl.java

/*** 系统日志实现类*/
@Service("sysLogService")
public class SysLogServiceImpl implements SysLogService {/** 日志表前缀 */private final static String TABLE_PREFIX = "SYS_LOG_";/*** 备份日志* @param createTime 时间* @param timeSuffix  后缀*/@Overridepublic void backupLog(String createTime, String timeSuffix) {String tableName = TABLE_PREFIX + timeSuffix;boolean flag = existTable(tableName);    //判断表是否存在if(!flag){//表不存在,先创建表createTable(tableName);}baseMapper.backupLog(createTime, tableName);}/*** 表是否存在* @param tableName 表名* @return    true存在,false不存在*/@Overridepublic boolean existTable(String tableName){int count = baseMapper.existTable(tableName);if(count > 0){return true;}return false;}/*** 创建表* @param tableName 表名*/@Overridepublic void createTable(String tableName){baseMapper.createTable(tableName);}
}

SysLogDAO.java

/*** 系统日志Mapper*/
public interface SysLogDAO{/*** 备份日志* @param createTime    时间* @param tableName   表名*/void backupLog(@Param("createTime")String createTime, @Param("tableName")String tableName);/*** 表是否存在* @param tableName  表名* @return    记录数*/int existTable(@Param("tableName")String tableName);/*** 创建表* @param tableName 表名*/void createTable(@Param("tableName")String tableName);
}

SysLogDAO.xml

<?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.xinghuo.modules.sys.dao.SysLogDAO"><!-- 备份日志 --><insert id="backupLog">INSERT INTO ${tableName} SELECT * FROM SYS_LOG WHERE CREATE_TIME <![CDATA[ <= ]]> #{createTime} </insert><!-- 查看表是否存在 --><select id="existTable" parameterType="String" resultType="Integer">select count(1) from user_tables where table_name = #{tableName} </select><!-- 创建表 --><update id="createTable" parameterType="String">CREATE TABLE ${tableName}(ID VARCHAR(36) NOT NULL,USER_ID VARCHAR(50),OPERATION VARCHAR(50),METHOD VARCHAR(200),PARAMS TEXT,TIME BIGINT NOT NULL,IP VARCHAR(64),CREATE_TIME TIMESTAMP(0),USER_NAME VARCHAR(100),TENANT_ID VARCHAR(36),RESULTS TEXT,PRIMARY KEY(ID))</update></mapper>

QuartzService.java

/*** 定时任务*/
@Component
@Slf4j
public class QuartzService {@Autowiredprivate SysLogService sysLogService;// 每天晚上10点启动@Scheduled(cron = "0 0 22 * * ?")public void deleteScheduled() {log.info("==================== 删除三个月前的日志数据开始 ====================");this.delMailLog();log.info("==================== 删除三个月前的日志数据结束 ====================");}/*** 删除三个月前的日志数据*/private void delMailLog() {try {Calendar c = Calendar.getInstance();c.setTime(new Date());c.add(Calendar.MONTH, - 3);  //设置为三个月前Date dateBefore = c.getTime();   //得到三个月前的时间SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");String time = simpleDateFormat.format(dateBefore);SimpleDateFormat sf = new SimpleDateFormat("yyyy");String timeSuffix = sf.format(dateBefore);//操作日志需要备份,因为可能需要统计登录次数sysLogService.backupLog(time, timeSuffix);//删除操作日志QueryWrapper<SysLogEntity> qw = new QueryWrapper<>();qw.le("CREATE_TIME", time);sysLogService.remove(qw);} catch (Exception e) {log.error("日志删除异常:{}",e);}}
}

注意:

1.需要在启动类增加注解@EnableScheduling

2.${tableName} 动态表名这里是美元符号$

Oracle 历史数据表迁移方案相关推荐

  1. mysql 数据转移历史表_mysql 历史数据表迁移方案

    当业务运行一段时间后,会出现有些表数据量很大,可能对系统性能产生不良的影响,常见的如订单表.登录log表等,这些数据很有时效性,比如我们一般很少去查上个月的订单,最多也就是报表统计会涉及到. 在我们的 ...

  2. mysql 历史数据表迁移方案

    当业务运行一段时间后,会出现有些表数据量很大,可能对系统性能产生不良的影响,常见的如订单表.登录log表等,这些数据很有时效性,比如我们一般很少去查上个月的订单,最多也就是报表统计会涉及到. 解决方案 ...

  3. 《 Oracle 10g-11g XTTS迁移方案》.pdf

    墨天轮文档:<Oracle 10g->11g XTTS迁移方案>:https://www.modb.co/doc/188(复制到浏览器中打开或者点击"阅读原文"可 ...

  4. oracle外部表迁移,海量数据迁移之外部表并行抽取

    在10g开始的新特性中,外部表是一个不容忽视的好工具.对于大型项目中海量数据使用sqlloader是一种全新的方式,不过很明显,sqlloader的可扩展性更强,但是基于oracle平台的数据迁移来说 ...

  5. mysql 历史数据迁移,MySQL 历史数据表迁移方法

    历史数据迁移分三个步骤进行: 在线库与历史库把需要迁移(或转入)的表都改成分区表 在线库上的历史数据迁移到历史库 在线库上删除已备份的历史数据 其中步骤1只执行一次,步骤2.3可以每月执行一次,即每月 ...

  6. 文档丨Oracle 三种迁移方案

    墨天轮文档:<Oracle DBA基础学习大纲>:https://www.modb.pro/doc/270(复制到浏览器中打开或者点击"阅读原文"即可下载)

  7. Oracle 导表异常处理方案 (解决空表导出出错问题)

    Select 'alter table '||table_name||' allocate extent;' from  user_tables where num_rows=0 or num_row ...

  8. oracle 物化视图、中间表的方案

    物化视图 有个项目因为有比较多的查询汇总,考虑到速度,所以使用了物化视图.简单的把用到的给整理了下.先看简单创建语句: create materialized view mv_materialized ...

  9. oracle mysql迁移方案_Oracle/云MySQL/MsSQL“大迁移”真相及最优方案

    最近一段时间碰到一些数据迁移的项目,如:Oracle迁移到MySQL,MsSQL迁移到MySQL,云MySQL迁移到本地MySQL.对于这方面做了系统的整理.包括:迁移方案的选择.如何跳出迁移遇到的坑 ...

  10. Oracle数据库联邦,使用联邦数据库将oracle表迁移到DB2(9.7)中的脚本说明

    由于兄弟项目组要测试,需要将oracle中的表迁移到db2中,操作步骤如下: #1 在windows数据库中建联邦数据库服务器\用户映射 connect to sample CREATE WRAPPE ...

最新文章

  1. 两分公支的IPSec***流量走总部测试
  2. 某程序员大佬北漂16年,从住地下室到身家千万,如今回老家躺平!
  3. memcache读书笔记(二)
  4. 三层学习------实践篇
  5. springMVC+ajaxFileUpload中文名乱码的问题
  6. Java EE 8的前5个新功能
  7. LoadRunner如何监控Linux下的系统资源
  8. 【ACDU推荐好文】手把手教你 DBCA 搭建 Oracle ADG
  9. canal mysql多节点_数据同步的终极解决方案,阿里巴巴开源的Canal框架当之无愧!!...
  10. iOS绘图框架CoreGraphics分析
  11. 714. 买卖股票的zui佳时机含手续费(JavaScript)
  12. 地铁19号线首段盾构区间双线贯通
  13. 每日算法系列【LeetCode 689】三个无重叠子数组的最大和
  14. Mac系统如何修复MAC硬盘权限
  15. 川大考研复试c语言参考书目_北京航空航天大学英语笔译考研参考书目-复试分数线...
  16. win10卸载软件_WIN10系统如何关闭/卸载自带杀毒软件
  17. 太阳天顶角与太阳方位角计算
  18. 解读后天性学者症候群:怎么一闷棍砸出个天才?
  19. office邮箱不能预览附件问题
  20. html canvas画背景图片,HTML5 canvas画布

热门文章

  1. 手把手教你搭建DHCP服务器
  2. Python实战:利用Uplift模型识别营销敏感用户提升市场策略(二)
  3. linux各个文件夹,linux各个目录文件夹含义
  4. 【不积跬步_无以至千里】 数学知识(不定时整理)
  5. 服务器开发系列(四)——网络基础
  6. 文明与征服新套路,北条点火队
  7. python 获取MP4视频第一帧 | Python工具类
  8. Duplicate entry '0' for key 'PRIMARY' 分析及其解决办法
  9. 查询mysql 的内存使用_如何查看MySQL内存使用情况
  10. 在MS Word 中添加 Mathtype 插件(vbe6ext.olb不能被加载问题 已解决)