按月拆分數據庫表--oracle

生產有一張日志表,數據量很大,需要按月進行存儲,存儲過程如下:

CREATE OR REPLACE PROCEDURE NEWLOG4_SUB_TABLE 
IStable_name1              VARCHAR2(50);create_table_sql         VARCHAR2(4000);insert_data_sql      VARCHAR2(4000);delete_data_sql      VARCHAR2(4000);
--  v_exists INT:=0;v_exists  NUMBER (10, 0);
BEGINSELECT 'NEWLOG4_' || TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'YYYYMM') INTO table_name1 FROM DUAL;select count(1) into v_exists from user_tables where table_name=UPPER(table_name1);--dbms_output.put_line(sname);--dbms_output.put_line(table_name1);if (v_exists <1)then-- dbms_output.put_line(sname);create_table_sql := 'create table ' || table_name1 || ' (autudt          TIMESTAMP(6),authentype      VARCHAR2(2000),userid          VARCHAR2(2000),orgid           VARCHAR2(2000),org2id          VARCHAR2(2000),realname        VARCHAR2(2000),success         VARCHAR2(2000),idpname         VARCHAR2(2000),idpip           VARCHAR2(2000),vistorip        VARCHAR2(2000),vistorbrowser   VARCHAR2(2000),spid            VARCHAR2(2000),spurl           VARCHAR2(2000),info            VARCHAR2(2000),autdesc         VARCHAR2(2000),taketime        VARCHAR2(2000),orgnamefullpath VARCHAR2(2000),ines            INTEGER default 0,logid           VARCHAR2(32),inputaccount    VARCHAR2(2000),channel         NUMBER(32),pushstate       NUMBER(2) default 0,appid           VARCHAR2(50))';EXECUTE IMMEDIATE create_table_sql;commit;end if;--將FATHER_TABLE表中取上月記錄 添加到新創建的分表中。insert_data_sql := 'INSERT INTO ' || table_name1 || ' SELECT * FROM NEWLOG4 WHERE autudt <(systimestamp - NUMTODSINTERVAL(30,''day'')) ';EXECUTE IMMEDIATE insert_data_sql;--刪除FATHER_TABLE表中時間在上個月范圍內的所有數據delete_data_sql := 'DELETE FROM NEWLOG4 WHERE autudt <(systimestamp-NUMTODSINTERVAL(30,''day''))';EXECUTE IMMEDIATE delete_data_sql;COMMIT;--EXCEPTION--WHEN OTHERS THEN--   ROLLBACK;
END NEWLOG4_SUB_TABLE;
create or replace procedure pro_exelog2 is
datetime INTEGER :=30; --Storage duration
v_name varchar2(40);
v_lastmouth varchar2(40);
v_count number:=0;
v_tbrecordname varchar2(10) :='newlog2_';
v_table varchar2(4000);
v_exists INT:=0;
beginselect tb_name,v_tbrecordname||to_char(sysdate-datetime,'yyyymm') into v_name,v_lastmouth from tb_record where type =2 and status=1;select count(1) into v_count from tb_record where type =2 and tb_name=UPPER(v_lastmouth);if v_count=0 thenbeginupdate tb_record set status=0 where type =2;  -- erase statusinsert into tb_record(type,tb_name,status) values(2,UPPER(v_lastmouth),1); --insert new table recordend;end if;select count(1) into v_exists from user_tables where table_name=UPPER(v_lastmouth);--create new table when time > 30 daysif v_exists!=1 thenbeginv_table:='create table '||v_name||' (AUTUDT TIMESTAMP(6),AUTHENTYPE VARCHAR2(2000),USERID VARCHAR2(2000),ORGID VARCHAR2(800),ORG2ID VARCHAR2(800),REALNAME VARCHAR2(800),SUCCESS VARCHAR2(20),IDPNAME VARCHAR2(2000),IDPIP VARCHAR2(2000),VISTORIP VARCHAR2(2000),VISTORBROWSER VARCHAR2(2000),SPID VARCHAR2(2000),SPURL VARCHAR2(2000),INFO VARCHAR2(2000),AUTDESC VARCHAR2(2000),TAKETIME VARCHAR2(2000),ORGNAMEFULLPATH VARCHAR2(2000))';EXECUTE IMMEDIATE v_table;commit;end;end if;v_table:='insert into '||v_lastmouth||' select * from newlog2 where autudt <(sysdate-'||datetime||')'; --insert new data from old tableEXECUTE IMMEDIATE v_table;commit;delete from newlog2 where autudt <(sysdate-datetime); --delete old datacommit;
end pro_exelog2;
create or replace procedure pro_exelog1 is
datetime INTEGER :=30;
v_name varchar2(40);
v_lastmouth varchar2(40);
v_count int:=0;
v_table varchar2(4000);
v_exists INT:=0;
v_tbrecordname varchar2(10) :='newlog1_';
beginselect tb_name ,v_tbrecordname||to_char(sysdate-datetime,'yyyymm') into v_name,v_lastmouth from tb_record where type =1 and status=1;select count(1) into v_count from tb_record where type =1 and tb_name=UPPER(v_lastmouth);if v_count=0 thenbeginupdate tb_record set status=0 where type=1;  -- erase statusinsert into tb_record(type,tb_name,status) values(1,UPPER(v_lastmouth),1); --insert new table recordend;end if;select count(1) into v_exists from user_tables where table_name=UPPER(v_lastmouth);--create new table when time > 30 daysif v_exists!=1 thenbeginv_table:='create table '||v_lastmouth||' (OPDT TIMESTAMP(6),OPUSERID VARCHAR2(32),OPUSERIP VARCHAR2(20),OPTYPE VARCHAR2(20),MAINOBJECTID VARCHAR2(32), MAINOBJECTTYPE VARCHAR2(20),MAINACTION VARCHAR2(50),BEFOREACTIONOBJECTJSONSTRING CLOB,AFTERACTIONOBJECTJSONSTRING CLOB,EXCCUTESTATUS VARCHAR2(2000),ERRORDESC VARCHAR2(2000),MAINOBJECTORG VARCHAR2(32),LOG_ID VARCHAR2(32) not null,PLATFORM VARCHAR2(20))';EXECUTE IMMEDIATE v_table;commit;end;end if;v_table:='insert into '||v_lastmouth||' select * from newlog1 where opdt <(sysdate-'||datetime||')'; --insert new data from old tableEXECUTE IMMEDIATE v_table;commit;delete from newlog1 where opdt <(sysdate-datetime); --delete old datacommit;
end pro_exelog1;
create or replace 
PROCEDURE PROC_CREATE_SUB_TABLE 
IStable_name              VARCHAR2(50);create_table_cursor     NUMBER(10);create_table_sql         VARCHAR2(1000);insert_data_sql      VARCHAR2(1000);delete_data_sql      VARCHAR2(1000);v_exists INT:=0;
BEGIN--生成分表的表名。SELECT 'NEWLOG4_' || TO_CHAR(ADD_MONTHS(SYSDATE, -1), 'YYYYMM') INTO table_name FROM DUAL;select count(1) into v_exists from user_tables where table_name=UPPER(table_name);if v_exists!=1  then create_table_cursor := DBMS_SQL.OPEN_CURSOR;--打開游標--拼出創建表的SQL語句,并執行。create_table_sql := 'create table ' || table_name || ' (autudt          TIMESTAMP(6),authentype      VARCHAR2(2000),userid          VARCHAR2(2000),orgid           VARCHAR2(2000),org2id          VARCHAR2(2000),realname        VARCHAR2(2000),success         VARCHAR2(2000),idpname         VARCHAR2(2000),idpip           VARCHAR2(2000),vistorip        VARCHAR2(2000),vistorbrowser   VARCHAR2(2000),spid            VARCHAR2(2000),spurl           VARCHAR2(2000),info            VARCHAR2(2000),autdesc         VARCHAR2(2000),taketime        VARCHAR2(2000),orgnamefullpath VARCHAR2(2000),ines            INTEGER default 0,logid           VARCHAR2(32),inputaccount    VARCHAR2(2000),channel         NUMBER(32),pushstate       NUMBER(2) default 0)';DBMS_SQL.PARSE(create_table_cursor, create_table_sql, DBMS_SQL.V7);DBMS_SQL.CLOSE_CURSOR(create_table_cursor);end if;--將FATHER_TABLE表中取上月記錄 添加到新創建的分表中。insert_data_sql := 'INSERT INTO ' || table_name || ' SELECT * FROM NEWLOG4 WHERE autudt <(systimestamp + NumToYMInterval(-1, 'MONTH')) ';v_table:='insert into '||v_lastmouth||' select * from newlog2 where autudt <(sysdate-'||datetime||')';EXECUTE IMMEDIATE insert_data_sql;--刪除FATHER_TABLE表中時間在上個月范圍內的所有數據delete_data_sql := 'DELETE FROM NEWLOG4 WHERE autudt <(systimestamp + NumToYMInterval(-1, 'MONTH')) ';EXECUTE IMMEDIATE delete_data_sql;COMMIT;EXCEPTIONWHEN OTHERS THENROLLBACK;
END PROC_CREATE_SUB_TABLE;
CREATE OR REPLACE PROCEDURE NEWLOG4_history_table
IS-- table_name1              VARCHAR2(50);-- create_table_sql         VARCHAR2(4000);-- insert_data_sql      VARCHAR2(4000);-- delete_data_sql      VARCHAR2(4000);
--  v_exists INT:=0;-- v_exists  NUMBER (10, 0);CURSOR cur ISselect * from NEWLOG4 t where autudt <(systimestamp-NUMTODSINTERVAL(30,'day'))and pushstate='3';TYPE rec IS TABLE OF NEWLOG4%ROWTYPE;recs rec;
BEGIN
OPEN cur;
WHILE (TRUE) LOOP
FETCH cur BULK COLLECT
INTO recs LIMIT 5000;
FORALL i IN 1 .. recs.COUNT
INSERT INTO NEWLOG4_DAY_INTERVAL_PARTITION VALUES recs (i);COMMIT;EXIT WHEN cur%NOTFOUND;END LOOP;CLOSE cur;--EXCEPTION--WHEN OTHERS THEN--   ROLLBACK;
END NEWLOG4_history_table;
CREATE OR REPLACE PROCEDURE NEWLOG4_day_TABLE (delete_date in varchar2)
ISinsert_data_sql      VARCHAR2(4000);delete_data_sql      VARCHAR2(4000);CURSOR cur IS
select * from NEWLOG4 t where TO_CHAR(t.autudt,'YYYY-MM-DD') = delete_date and pushstate='3';
TYPE rec IS TABLE OF NEWLOG4%ROWTYPE;
recs rec;
BEGIN
OPEN cur;
WHILE (TRUE) LOOP
FETCH cur BULK COLLECT
INTO recs LIMIT 5000;
FORALL i IN 1 .. recs.COUNT
--EXECUTE IMMEDIATE insert_data_sql;
INSERT INTO NEWLOG4_DAY_INTERVAL_PARTITION VALUES recs (i);COMMIT;EXIT WHEN cur%NOTFOUND;END LOOP;CLOSE cur;--EXCEPTION--WHEN OTHERS THEN--   ROLLBACK;
END NEWLOG4_day_TABLE;
CREATE OR REPLACE PROCEDURE NEWLOG4_SUB_test (delete_date in varchar2)
IS-- table_name1              VARCHAR2(50);-- create_table_sql         VARCHAR2(4000);insert_data_sql      VARCHAR2(4000);delete_data_sql      VARCHAR2(4000);
--  v_exists INT:=0;--  v_exists  NUMBER (10, 0);CURSOR cur IS
select * from NEWLOG4 t where TO_CHAR(t.autudt,'YYYY-MM-DD') = delete_date and pushstate='3';
TYPE rec IS TABLE OF NEWLOG4%ROWTYPE;
recs rec;
BEGIN--將FATHER_TABLE表中取上月記錄 添加到新創建的分表中。-- insert_data_sql := 'INSERT INTO ' || table_name1 || ' SELECT * FROM NEWLOG4 WHERE autudt <(systimestamp - NUMTODSINTERVAL(30,''day'')) and pushstate=''3''';-- EXECUTE IMMEDIATE insert_data_sql;--insert_data_sql :='INSERT INTO '||history_table|| 'VALUES recs (i)'
OPEN cur;
WHILE (TRUE) LOOP
FETCH cur BULK COLLECT
INTO recs LIMIT 5000;
FORALL i IN 1 .. recs.COUNT
--EXECUTE IMMEDIATE insert_data_sql;
INSERT INTO NEWLOG4_202103_10 VALUES recs (i);COMMIT;EXIT WHEN cur%NOTFOUND;END LOOP;CLOSE cur;--insert_data_sql :='alter session enable parallel dml';--EXECUTE IMMEDIATE insert_data_sql;-- delete_data_sql :='delete /*+parallel(12)*/  from NEWLOG4  nologging  where TO_CHAR(autudt,''YYYY-MM-DD'') =''2021-03-10''and pushstate=''3''';--delete_data_sql :='delete /*+parallel(12)*/  from NEWLOG4  nologging  where TO_CHAR(autudt,''YYYY-MM-DD'') =' ||delete_date|| 'and pushstate=''3''';--EXECUTE IMMEDIATE delete_data_sql;--COMMIT;--EXCEPTION--WHEN OTHERS THEN--   ROLLBACK;
END NEWLOG4_SUB_test;
2.alter table tab1 nologging;insert /*+ append */ into tab1 select * from tab2;commit;alter table tab1 logging;該方法會使得產生arch大大減少,并且在一定程度上提高時間,根據經驗,千萬級的數據可在45分鐘內完成。但是請注意,該方法適合單進程的串行方式,如果當有多個進程同時運行時,后發起的進程會有enqueue的等待。注意此方法千萬不能dataguard上用(不過要是在database已經force logging那也是不怕的,呵呵)!!3. insert into tab1 select /*+ parallel */ * from tab2;commit;對于select之后的語句是全表掃描的情況,我們可以加parallel的hint來提高其并發,這里需要注意的是最大并發度受到初始化參數parallel_max_servers的限制,并發的進程可以通過v$px_session查看,或者ps -ef |grep ora_p查看。4. alter session enable parallel dml;insert /*+ parallel */ into tab1 select * from tab2;commit;與方法2相反,并發的insert,尚未比較和方法2哪個效率更高(偶估計是方法2快),有測試過的朋友歡迎補充。5.insert into tab1 select * from tab2 partition (p1);insert into tab1 select * from tab2 partition (p2);insert into tab1 select * from tab2 partition (p3);insert into tab1 select * from tab2 partition (p4);對于分區表可以利用tab1進行多個進程的并發insert,分區越多,可以啟動的進程越多。我曾經試過insert 2.6億行記錄的一個表,8個分區,8個進程,如果用方法2,單個進程完成可能要40分鐘,但是由于是有8個分區8個進程,后發進程有enqueue,所以因此需要的時間為40分鐘×8;但是如果用方法5,雖然單個進程需要110分鐘,但是由于能夠并發進程執行,所以總共需要的時間就約為110分鐘了。6.DECLARETYPE dtarray IS TABLE OF VARCHAR2(20) INDEX BY BINARY_INTEGER;v_col1 dtarray;v_col2 dtarray;v_col3 dtarray;BEGINSELECT col1, col2, col3 BULK COLLECTINTO v_col1, v_col2, v_col3FROM tab2;FORALL i IN 1 .. v_col1.COUNTinsert into tab1 WHERE tab1.col1 = v_col1;END;用批量綁定(bulk binding)的方式。當循環執行一個綁定變量的sql語句時候,在PL/SQL 和SQL引擎(engines)中,會發生大量的上下文切換(context switches)。使用bulk binding,能將數據批量的從plsql引擎傳到sql引擎,從而減少上下文切換過程,提升效率。該方法比較適合于在線處理,不必停機
————————————————7.sqlplus -s user/pwd< runlog.txtset copycommit 2;set arraysize 5000;copy from user/pwd@sid -to user/pwd@sid -insert tab1 using select * from tab2;exitEOF用copy的方法進行插入,注意此處insert沒有into關鍵字。該方法的好處是可以設置copycommit和arrarysize來一起控制commit的頻率,上面的方法是每10000行commit一次

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/535350.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/535350.shtml
英文地址,請注明出處:http://en.pswp.cn/news/535350.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

plsql定時器

Oralce中的任務有2種&#xff1a;Job和Dbms_job&#xff0c;兩者的區別有&#xff1a; 1&#xff0e; jobs是oracle數據庫的對象&#xff0c; dbms_jobs只是jobs對象的一個實例&#xff0c; 就像對于tables&#xff0c; emp和dept都是表的實例。 2&#xff0e; 創建方式也有…

PL/SQL批處理語句:BULK COLLECT 和 FORALL

PL/SQL程序中運行SQL語句是存在開銷的&#xff0c;因為SQL語句是要提交給SQL引擎處理&#xff0c;這種在PL/SQL引擎和SQL引擎之間的控制轉移叫做上下文卻換&#xff0c;每次卻換時&#xff0c;都有額外的開銷 請看下圖&#xff1a; 但是&#xff0c;FORALL和BULK COLLEC…

oracle 中DATETIME與TIMESTAMP區別

1.DATETIME的日期范圍是1001——9999年&#xff0c;TIMESTAMP的時間范圍是1970——2038年。 2.DATETIME存儲時間與時區無關&#xff0c;TIMESTAMP存儲時間與時區有關&#xff0c;顯示的值也依賴于時區。在mysql服務器&#xff0c;操作系統以及客戶端連接都有時區的設置。 3.DAT…

PARALLEL(并行)

在Oracle中&#xff0c;PARALLEL&#xff08;并行&#xff09;方式最大化調用計算機資源來成倍提高數據分析效率。 1&#xff0e; 用途 強行啟用并行度來執行當前SQL。這個在Oracle 9i之后的版本可以使用&#xff0c;之前的版本現在沒有環境進行測試。也就是說&#xff0c;加…

Oracle數據庫查詢優化

1.對查詢進行優化&#xff0c;應盡量避免全表掃描&#xff0c;首先應考慮在 where 及 order by 涉及的列上建立索引。 2.應盡量避免在 where 子句中對字段進行 null 值判斷&#xff0c;否則將導致引擎放棄使用索引而進行全表掃描&#xff0c;如&#xff1a; select id from t w…

redis-full-check

https://github.com/alibaba/RedisFullCheck/releases redis-full-check是阿里云Redis&MongoDB團隊開源的用于校驗2個redis數據是否一致的工具。 ??redis-full-check通過全量對比源端和目的端的redis中的數據的方式來進行數據校驗&#xff0c;其比較方式通過多輪次比較&a…

2021-06-22

服務器信息 [rootiZs7z01dz0z12dyttz9zn5Z cluster]# /app/redis/redis-3.2.1/src/redis-cli -c -h 10.252.120.9 -p 8003 10.252.120.9:8003> cluster nodes b1f543d646c5c97a70b0635439a44a72f8a143b1 10.252.120.10:8004 master - 0 1624349601417 7 connected 0-5460 1…

Docker目錄掛載

Docker容器啟動的時候&#xff0c;如果要掛載宿主機的一個目錄&#xff0c;可以用-v參數指定。 譬如我要啟動一個centos容器&#xff0c;宿主機的/test目錄掛載到容器的/soft目錄&#xff0c;可通過以下方式指定&#xff1a; # docker run -it -v /test:/soft centos /bin/ba…

Redis主從復制原理學習

Redis主從復制原理學習總結 - 運維筆記 和Mysql主從復制的原因一樣&#xff0c;Redis雖然讀取寫入的速度都特別快&#xff0c;但是也會產生讀壓力特別大的情況。為了分擔讀壓力&#xff0c;Redis支持主從復制&#xff0c;Redis的主從結構可以采用一主多從或者級聯結構&#xff…

redis數據恢復

公司線上一個項目數據存儲采用MySQL&#xff0c;共分為10個庫&#xff0c;分布在4臺機器上&#xff0c;每個庫數據量約為10G&#xff0c;各機器均采用RAID5加速磁盤訪問&#xff1b; 當同時在線人數達高峰期&#xff08;10w&#xff09;&#xff0c;DB磁盤IO壓力巨大&#xff0…

Redis哨兵模式(sentinel)學習總結及部署記錄(主從復制、讀寫分離、主從切換)

Redis的集群方案大致有三種&#xff1a;1&#xff09;redis cluster集群方案&#xff1b;2&#xff09;master/slave主從方案&#xff1b;3&#xff09;哨兵模式來進行主從替換以及故障恢復。 一、sentinel哨兵模式介紹 Sentinel(哨兵)是用于監控redis集群中Master狀態的工具&…

Redis之Redis內存模型

Redis是目前最火爆的內存數據庫之一&#xff0c;通過在內存中讀寫數據&#xff0c;大大提高了讀寫速度&#xff0c;可以說Redis是實現網站高并發不可或缺的一部分。 我們使用Redis時&#xff0c;會接觸Redis的5種對象類型&#xff08;字符串、哈希、列表、集合、有序集合&…

MySQL 數據庫誤刪除后的數據恢復操作說明

在日常運維工作中&#xff0c;對mysql數據庫的備份是萬分重要的&#xff0c;以防在數據庫表丟失或損壞情況出現&#xff0c;可以及時恢復數據。 線上數據庫備份場景&#xff1a; 每周日執行一次全量備份&#xff0c;然后每天下午1點執行MySQLdump增量備份. 下面對這種備份方案…

MySQL 之binlog日志說明及利用binlog日志恢復數據操作記錄

眾所周知&#xff0c;binlog日志對于mysql數據庫來說是十分重要的。在數據丟失的緊急情況下&#xff0c;我們往往會想到用binlog日志功能進行數據恢復&#xff08;定時全備份binlog日志恢復增量數據部分&#xff09;&#xff0c;化險為夷&#xff01; 一、簡單了解binlog MySQ…

zabbix巡檢腳本

#!/bin/bash BIN/usr/local/zabbix/binpasswort() { name$2 while read line do ipecho $line|awk -F {print $1} timeecho $line|awk -F {print $2} echo -e "${name}passport${ip}探活時間\t $time" done <$1 }for i in 100.245.160.113 100.245.160.141 1…

mysqldump備份(全量+增量)

在日常運維工作中&#xff0c;對mysql數據庫的備份是萬分重要的&#xff0c;以防在數據庫表丟失或損壞情況出現&#xff0c;可以及時恢復數據。 線上數據庫備份場景&#xff1a; 每周日執行一次全量備份&#xff0c;然后每天下午1點執行MySQLdump增量備份. 下面對這種備份方案…

查找指定日期數據所在分區數據

select a.subobject_namefrom dba_objects a join (select dbms_rowid.rowid_object(rowid) object_idfrom NEWLOG4 where TO_CHAR(autudt,YYYY-MM-DD) 2021-06-22) b on a.object_id b.object_id and object_name UPPER(NEWLOG4) group by a.subobject_name

統計內存使用率shell

#!/bin/bashdatedate "%Y-%m-%d %H:%M:%S"#顯示消耗資源內存最高的進程名firstps aux | grep -v "grep" | grep -v "USER" | sort -rn -k 4 | head -4 | awk -F {print $13} | sed -n 1pSecondps aux | grep -v "grep" | grep -v &q…

Oracle 11g系統自動收集統計信息

從Oracle Database 10g開始&#xff0c;Oracle在建庫后就默認創建了一個名為GATHER_STATS_JOB的定時任務&#xff0c;用于自動收集CBO的統計信息&#xff0c;調用DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC收集統計信息。該過程首先檢測統計信息缺失和陳舊的對象。然后確定優先…

Redis監控指標

監控指標 ?性能指標&#xff1a;Performance?內存指標: Memory?基本活動指標&#xff1a;Basic activity?持久性指標: Persistence?錯誤指標&#xff1a;Error 性能指標&#xff1a;Performance NameDescriptionlatencyRedis響應一個請求的時間instantaneous_ops_per_s…