以下程序需要将近5个小时才能完成130000条记录。尝试过优化它。有没有办法优化它? 如果我在每个"之后为所有人做出承诺" ,这会提高性能吗? 此外,我已经给出了1000条记录的限制,所以这里是提交1000条记录处理还是计数为0? 数据库版本:oracle 10g
我正在运行以下程序:
create or replace PROCEDURE WeeklyClearQwAcctActivityLoad
AS
v_no_of_Days_retention number;
jobname VARCHAR2 (30);
loadstartdt DATE;
rcdcnt number;
errorcode NUMBER;
errormsg VARCHAR2 (100);
/* Identify those records for which all CUST_ACCT_ID under the same Parent_id are closed (before retention days ) */
CURSOR getdataforhist
IS
select /*+ parallel(qa2,128) */ CUST_ACCT_ID from qw_account qa2
where exists
( select /*+ parallel(qaa2,128) */ 1 from QW_ACCT_ACTIVITY qaa2
where qaa2.cust_acct_id = qa2.cust_acct_id
and qaa2.actvy_end_date < sysdate - v_no_of_Days_retention
)
and not exists
(
select 1 from (
select /*+ parallel(qa,128) */ qa.PARENT_ID pidd from qw_account qa
where exists
( select /*+ parallel(qaa,128) */ 1 from QW_ACCT_ACTIVITY qaa
where qaa.cust_acct_id = qa.cust_acct_id
and qaa.actvy_end_date > sysdate - v_no_of_Days_retention
)
) pp where pp.pidd = qa2.PARENT_ID
);
TYPE t_getDataForHist IS TABLE OF qw_acct_activity.cust_acct_id%TYPE;
l_getDataForHist t_getDataForHist;
CURSOR orph_product
IS
SELECT /*+ parallel( ram , 128) */ ram.rcr_prod_acct_id
FROM rcr_acct_mapping ram
WHERE 1=1
AND ram.cust_acct_id IS NOT NULL
AND EXISTS
( SELECT /*+ parallel( rap , 128) */ 1
FROM rcr_acct_profile rap
WHERE rap.rcr_prod_acct_id = ram.rcr_prod_acct_id
AND rap.cust_acct_id = ram.cust_acct_id
AND rap.prod_acct_status in ('ACTIVE','INACTIVE','SUSPENDED')
)
AND NOT EXISTS
( SELECT /*+ parallel( qaa , 128 */ 1
FROM qw_acct_activity qaa
WHERE qaa.cust_acct_id = ram.cust_acct_id
);
TYPE t_orph_product is table of rcr_acct_mapping.rcr_prod_acct_id%TYPE;
l_orph_product t_orph_product;
cnt number default 0;
BEGIN
jobname := 'WEEKLY_CLEAN_QW_ACCT_ACTIVITY';
loadstartdt := SYSDATE;
rcdcnt := 0;
INSERT INTO rcr_stage_audit (job_name,load_start_date,load_end_date,record_cnt,processed,process_date,process_cnt,ignore_cnt)
VALUES (jobname,loadstartdt,NULL,NULL,'N',loadstartdt,NULL,NULL );
COMMIT;
BEGIN
SELECT VALUE into v_no_of_Days_retention
FROM rcr_online_svc_app_config
WHERE NAME = 'noofdaystoenddateqwacctactivity';
EXCEPTION
WHEN NO_DATA_FOUND
THEN
errorcode := SQLCODE;
errormsg := 'no of days to end date qw_accta_ctivity is not defined in rcr_code_translation table';
raise_application_error (-20101, errorcode || ' - ' || errormsg, TRUE);
END;
OPEN getDataForHist;
LOOP
FETCH getdataforhist BULK COLLECT INTO l_getdataforhist LIMIT 1000;
--EXIT WHEN getdataforhist%NOTFOUND ;
EXIT WHEN l_getdataforhist.COUNT = 0;
-- FORALL indx IN 1 .. l_getdataforhist.count
-- insert into TEMPSLOT (CUST_ACCT_ID) values ( l_getdataforhist(indx) ) ;
FORALL indx1 IN 1 .. l_getdataforhist.count
INSERT INTO qw_acct_activity_hist
SELECT qaa.*, SYSDATE
FROM qw_acct_activity qaa
WHERE CUST_ACCT_ID = ( l_getdataforhist(indx1) );
FORALL indx2 IN 1 .. l_getdataforhist.count
DELETE FROM qw_acct_activity
WHERE CUST_ACCT_ID = ( l_getdataforhist(indx2) );
rcdcnt := rcdcnt + sql%rowcount;
COMMIT;
END LOOP;
CLOSE getDataForHist;
--- Clean porduct tables for orphan CUST_ACCT_ID
OPEN orph_product;
LOOP
FETCH orph_product BULK COLLECT INTO l_orph_product LIMIT 1000;
EXIT WHEN l_orph_product.COUNT = 0;
FORALL indx10 IN 1 .. l_orph_product.COUNT
INSERT INTO rcr_acct_mapping_hist
SELECT a.*
FROM rcr_acct_mapping a
WHERE rcr_prod_acct_id = ( l_orph_product(indx10) );
FORALL indx11 IN 1 .. l_orph_product.COUNT
DELETE FROM rcr_acct_mapping WHERE rcr_prod_acct_id = ( l_orph_product(indx11) );
FORALL indx12 IN 1 .. l_orph_product.COUNT
DELETE FROM rcr_addt_acct_prof_detail WHERE rcr_prod_acct_id = ( l_orph_product(indx12) );
FORALL indx13 IN 1 .. l_orph_product.COUNT
DELETE FROM rcr_acct_profile_detail WHERE rcr_prod_acct_id = ( l_orph_product(indx13) );
FORALL indx14 IN 1 .. l_orph_product.COUNT
DELETE FROM rcr_acct_profile WHERE rcr_prod_acct_id = ( l_orph_product(indx14) );
COMMIT;
END LOOP;
close orph_product;
UPDATE rcr_stage_audit
SET load_end_date = SYSDATE,
record_cnt = rcdcnt,
processed = 'Y'
WHERE job_name = jobname
AND process_date = loadstartdt
AND load_start_date = loadstartdt;
COMMIT;
EXCEPTION
WHEN OTHERS
THEN
errorcode := SQLCODE;
errormsg := substr(sqlerrm,1,255);
raise_application_error (-20102, errorcode || ' - ' || errormsg, TRUE);
END WeeklyClearQwAcctActivityLoad;
答案 0 :(得分:3)
我向你推荐的一个建议是避免显式循环和游标。它会导致性能不佳,尤其是当您可以直接使用
时insert into <table_name>(columns) select <your_query_goes_here>
这肯定会比循环结构执行得更快。实际上,您可以使用一百万条记录生成的表中的简单基准重现此行为。
因此,简而言之,请尽量避免循环,并且您的代码看起来也会更具可读性且不易出错。
我做了一次基准测试,其中1000万条记录中只有大约12,000条记录需要更新,显式循环与隐式循环导致的时间是1分10秒v / s 1秒。
答案 1 :(得分:0)
使用oraclebug或dbms_monitor等oracle工具跟踪它,并使用tkprof或其他分析工具检查跟踪文件。如下所示:
1.提取sid
2.在sqlplus中运行:oradebug setorapid xxxx
3.在sqlplus中运行:oradebug tracefile_name
4.在os运行完成后,在跟踪文件上运行tkprof。(其他工具也可用)。
5.在跟踪文件中检查长节并处理它们