最近項目中牽涉到把mysql中一個表的數據牽移oracle上來,並只保存三個月的數據,由於此表的數據增加量比較大,現在是每個月三百萬,以後會更多,所
以oracle表在實現時考慮到完整的增加與刪除的策略!
下面將記錄再實現過程中所遇到的所有問題:
1.對於數據量的不斷增加,由於跟據時間特性,所以採用按時間進行分區的方式實現
2.對於增加與刪除分區,採用存儲過程來實現,採用定時執行的存儲過程JOB,每月增加與刪除一次分區。
3.對於表字段自增採用序列的方式實現。
4.對於以前數據牽移,在表建好後,一部分數據再建立索引以前牽移,等牽移完整後,切換數據庫,切換成功後再牽移另一部分數據。
對於表結構的實現以及存儲過程的建立語法如下:(網上參考別人的方式,實現的)
創建序列:
drop sequence loginid_seq;
create sequence loginid_seq
minvalue 1
nomaxvalue
start with 1
increment by 1
nocache;
分區表結構創建:
drop table tb_domainmail_weblogin_log;
CREATE TABLE tb_domainmail_weblogin_log(
login_id number primary key,
domain varchar2(100) not null,
account_name varchar2(50) not null,
login_type varchar2(20) not null,
login_time date default sysdate,
login_ip varchar2(130) default NULL
)
partition by range(login_time)
(
partition P_weblogin_20100115 values less than(to_date('2010-01-15 12:00:00','YYYY-MM-DD HH24:mi:ss')),--測試所用
partition P_weblogin_20110115 values less than(to_date('2011-01-15 12:00:00','YYYY-MM-DD HH24:mi:ss')),
partition P_weblogin_20110215 values less than(to_date('2011-02-15 12:00:00','YYYY-MM-DD HH24:mi:ss'))
);
--增加一個分區
alter table tb_domainmail_weblogin_log add partition P_weblogin_20110315 values less than(to_date('2011-03-15 12:00:00','YYYY-MM-DD
HH24:mi:ss'));
--增加分區的存儲過程
CREATE OR REPLACE PROCEDURE WEBLOGIN_ADD_PARTITION_PROC(
partNum NUMBER, --添加分區的個數
partDay NUMBER --分區之間的時間間隔
) AS
v_SqlExec VARCHAR2(2000); --DDL語句變量
v_PartDate VARCHAR2(20); --創建分區的日期(YYYYMMDD)
v_PartDate1 VARCHAR2(30); --創建分區的日期(YYYYMMDD)
v_err_num NUMBER; --ORA錯誤號
v_err_msg VARCHAR2(100); --錯誤描述
v_PartDate_max VARCHAR2(20); --test_log 表分區的最大日期
BEGIN
--查詢已創建 tb_domainmail_weblogin_log 表分區的最大日期
--P_weblogin_20110215
select max(SUBSTR(partition_name,12,8)) into v_PartDate_max
from user_tab_partitions
WHERE table_name=UPPER('tb_domainmail_weblogin_log');
FOR i IN 1..partNum LOOP
--創建 tb_domainmail_weblogin_log 表分區
IF v_PartDate_max<to_char(sysdate+(i*partDay),'yyyymmdd') THEN
v_PartDate:=to_char(SYSDATE+(i*partDay),'YYYYMMDD');
v_PartDate1:=to_char(SYSDATE+(i*partDay),'YYYY-MM-DD HH24:mi:ss');
v_SqlExec:='ALTER TABLE tb_domainmail_weblogin_log ADD PARTITION P_WEBLOGIN_' || v_PartDate ||
' values less than (to_date(''' || v_PartDate1 || ''',''YYYY-MM-DD HH24:mi:ss''))';
dbms_output.put_line('創建 tb_domainmail_weblogin_log 表分區' || i || '='||v_SqlExec);
DBMS_Utility.Exec_DDL_Statement(v_SqlExec);
END IF;
END LOOP;
EXCEPTION
WHEN OTHERS THEN
v_err_num := SQLCODE;
v_err_msg := SUBSTR(SQLERRM, 1, 100);
dbms_output.put_line('WEBLOGIN_ADD_PARTITION_PROC執行出現異常,錯誤碼='|| v_err_num || '錯誤描述=' || v_err_msg);
END WEBLOGIN_ADD_PARTITION_PROC;
--再次,建立刪除分區的存儲過程
CREATE OR REPLACE PROCEDURE WEBLOGIN_DROP_PARTITION_PROC(
beforeDays NUMBER --刪除多少天前的分區
)
As
v_SqlExec VARCHAR2(2000); --DDL語句變量
v_err_num NUMBER; --ORA錯誤號
v_err_msg VARCHAR2(100); --錯誤描述
--查找beforeDays天前存在的 tb_domainmail_weblogin_log 表分區
cursor cursor_testlog_part is
select partition_name from user_tab_partitions
WHERE table_name=UPPER('tb_domainmail_weblogin_log')
AND SUBSTR(partition_name,12,8)<TO_CHAR(SYSDATE-beforeDays,'YYYYMMDD')
ORDER BY partition_name;
record_testlog_oldpart cursor_testlog_part%rowType;
BEGIN
open cursor_testlog_part;
loop
fetch cursor_testlog_part into record_testlog_oldpart;
exit when cursor_testlog_part%notfound;
--刪除 tb_domainmail_weblogin_log 表分區
v_SqlExec:='ALTER TABLE tb_domainmail_weblogin_log DROP PARTITION ' ||
record_testlog_oldpart.partition_name;
dbms_output.put_line('刪除tb_domainmail_weblogin_log表分區='||v_SqlExec);
DBMS_Utility.Exec_DDL_Statement(v_SqlExec);
end loop;
close cursor_testlog_part;
EXCEPTION
WHEN OTHERS THEN
v_err_num := SQLCODE;
v_err_msg := SUBSTR(SQLERRM, 1, 100);
dbms_output.put_line('WEBLOGIN_DROP_PARTITION_PROC執行出現異常,錯誤碼='|| v_err_num || '錯誤描述=' || v_err_msg);
END WEBLOGIN_DROP_PARTITION_PROC;
/
--執行增加的存儲過程:
CREATE OR REPLACE PROCEDURE WEBLOGIN_EXEC_ADD_PROC AS
v_err_num NUMBER; --ORA錯誤號
v_err_msg VARCHAR2(100); --錯誤描述
v_date VARCHAR2(2):='15'; --每個月的15號做此事。
BEGIN
--2代表創建一個分區,30代表分區大小爲30天的數據。
IF v_date=to_char(SYSDATE,'DD') THEN
WEBLOGIN_ADD_PARTITION_PROC(2,'31');
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
v_err_num := SQLCODE;
v_err_msg := SUBSTR(SQLERRM, 1, 100);
dbms_output.put_line('WEBLOGIN_EXEC_ADD_PROC執行出現異常,錯誤碼='|| v_err_num || '錯誤描述=' || v_err_msg);
END WEBLOGIN_EXEC_ADD_PROC;
--執行刪除的存儲過程:
CREATE OR REPLACE PROCEDURE WEBLOGIN_EXEC_DROP_PROC AS
v_err_num NUMBER; --ORA錯誤號
v_err_msg VARCHAR2(100); --錯誤描述
v_date VARCHAR2(2):='15'; --每個月的15號做此事。
BEGIN
--刪除3個月前的數據 100代表100天
IF v_date=to_char(SYSDATE,'DD') THEN
WEBLOGIN_DROP_PARTITION_PROC(100);
COMMIT;
END IF;
EXCEPTION
WHEN OTHERS THEN
v_err_num := SQLCODE;
v_err_msg := SUBSTR(SQLERRM, 1, 100);
dbms_output.put_line('WEBLOGIN_DROP_PARTITION_PROC執行出現異常,錯誤碼='|| v_err_num || '錯誤描述=' || v_err_msg);
END WEBLOGIN_EXEC_DROP_PROC;
--建立JOB定時執行存儲過程
create or replace procedure WEBLOGIN_JOBS_PROC as
job1 number; --每個月15號18點創建分區
job2 number; --每個月15號23點刪除分區
v_err_num NUMBER; --ORA錯誤號
v_err_msg VARCHAR2(100); --錯誤描述
begin
dbms_job.submit(job1,'WEBLOGIN_EXEC_ADD_PROC;',sysdate,'SYSDATE + (18*60)/(24*60)');
dbms_job.submit(job2,'WEBLOGIN_EXEC_DROP_PROC;',sysdate,'SYSDATE + (23*60)/(24*60)');
commit;
EXCEPTION
WHEN OTHERS THEN
v_err_num := SQLCODE;
v_err_msg := SUBSTR(SQLERRM, 1, 100);
dbms_output.put_line('WEBLOGIN_JOBS_PROC執行出現異常,錯誤碼='|| v_err_num || '錯誤描述=' || v_err_msg);
end WEBLOGIN_JOBS_PROC;
-執行定時工作JOB存儲過程
execute WEBLOGIN_JOBS_PROC;
--刪除存儲過程
drop PROCEDURE WEBLOGIN_JOBS_PROC;
execute WEBLOGIN_EXEC_ADD_PROC;
以上爲測試時實現的所有存儲過程,都已經通過!