当业务运行一段时间后,会出现有些表数据量很大,可能对系统性能产生不良的影响,常见的如订单表、登录log表等,这些数据很有时效性,比如我们一般很少去查上个月的订单,最多也就是报表统计会涉及到。
解决方案:创建一个存储过程,每月定时调用,查出上个月数据保存到新建的表中,新表命名以月份为后缀,删除主表中上个月数据。
存储过程
CREATE OR REPLACE
procedure operate_log_proc(return_code OUT VARCHAR2,
return_msg OUT VARCHAR2)
authid current_user
is
err_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);
begin
return_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_name
FROM 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:00
SELECT 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;
EXCEPTION
WHEN OTHERS THEN
return_msg := '过程[OPERATE_LOG_PROC]出错,' || '第[' || err_index ||
']块语句出错';
return_code := '0';
ROLLBACK;
end operate_log_proc;
说明:operate_log_proc存储过程名称,Operate_Log表名。authid current_user关键字给存储过程授权,不然报错找不到表。
定时任务
BEGIN
dbms_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;
说明:没有参数的存储过程,可以直接用存储过程名称加上";"分号。需要权限才能创建。