2016-05-11 93 views
0

我有一個過程可以生成200萬條記錄到一個臨時表中(預計增加到900萬)。然後,臨時表中的數據應該被複制到一個CLOB中並存儲回數據庫柱。將表內容複製到CLOB變量

目前,我正面臨將臨時表中的數據複製到需要12分鐘的CLOB列的性能問題。代碼片段如下。

有沒有更好的方法來做到這一點?

代碼段

DECLARE 
    lv_clob_temp CLOB; 
    lv_content_file REPORT_DETAILS.content_file%type; 
    lv_rev_header_file REPORT_DETAILS.rev_header_file%type; 
    lv_rev_content_file REPORT_DETAILS.rev_content_file%type; 
    type rec_report_temp is table of REPORT_TEMP%ROWTYPE; 
    tbl_report_temp rec_report_temp; 
    lv_bulk_limit pls_integer := 100000; 
BEGIN 

    -- fetch master data for the report 
    SELECT 
    content_file 
    , rev_content_file 
    INTO 
    lv_content_file 
    , lv_rev_content_file 


    FROM REPORT_DETAILS 
    WHERE rep_id = 1 for update; 

dbms_lob.createtemporary(lv_clob_temp, TRUE, DBMS_LOB.SESSION); 

--Data for the content extract 
    open cur_rec for 'SELECT COL1, COL2, COL3, COL4, COL5, COL6, COL7 from REPORT_TEMP'; 

    loop 
    FETCH cur_rec BULK COLLECT INTO tbl_report_temp LIMIT lv_bulk_limit; 
    EXIT WHEN tbl_report_temp.count = 0; 

    for i in 1..tbl_report_temp.count 
    loop 
    lv_clob_temp := tbl_report_temp(i).COL1 
    ||','||tbl_report_temp(i).COL2 
    ||','||to_char(tbl_report_temp(i).COL3,'DD/MM/YYYY') 
    ||','||to_char(tbl_report_temp(i).SPAD,'DD/MM/YYYY') 
    ||','||to_char(tbl_report_temp(i).COL5,'DD/MM/YYYY') 
    ||','||tbl_report_temp(i).COL7 
    ||','||to_char(tbl_report_temp(i).COL6,'DD/MM/YYYY') 
    || lv_crlf; 

    DBMS_LOB.APPEND(lv_content_file, lv_clob_temp); 

    lv_clob_temp := tbl_report_temp(i).COL1 
    ||','||tbl_report_temp(i).COL2 
    ||','||to_char(tbl_report_temp(i).COL3,'DD/MM/YYYY') 
    ||','||to_char(tbl_report_temp(i).SPAD,'DD/MM/YYYY') 
    ||','||to_char(tbl_report_temp(i).COL5,'DD/MM/YYYY') 
    || lv_crlf; 

    DBMS_LOB.APPEND(lv_rev_content_file, lv_clob_temp); 


    end loop; 

    end loop; 

    UPDATE REPORT_DETAILS 
    set content_file = lv_content_file 
    , rev_content_file = lv_rev_content_file 
    WHERE rep_id = 1; 

    COMMIt; 

END; 
+0

同類問題。 http://stackoverflow.com/questions/2297672/pl-sql-array-to-clob – Alwyn

回答

0

我的朋友建議我用低於給定的腳本,

爲了實現CLOB串聯使用功能stragg_clob(運行下面的腳本)。

create or replace type rmd_agg_type as object 
    (
     total clob, 

     static function 
     ODCIAggregateInitialize(sctx IN OUT rmd_agg_type) 
     return number, 

     member function 
     ODCIAggregateIterate(self IN OUT rmd_agg_type ,value IN varchar2) 
     return number, 

     member function 
     ODCIAggregateTerminate(self IN rmd_agg_type, returnValue OUT clob, flags IN number) 
     return number, 

     member function 
     ODCIAggregateMerge(self IN OUT rmd_agg_type, ctx2 IN rmd_agg_type) 
     return number 
    ); 
    /

    create or replace type body rmd_agg_type 
    is 

     static function ODCIAggregateInitialize(sctx IN OUT rmd_agg_type) 
     return number 
     is 
     begin 
     sctx := rmd_agg_type(null); 
     return ODCIConst.Success; 
     end; 

     member function ODCIAggregateIterate(self IN OUT rmd_agg_type, 
              value IN varchar2) 
     return number 
     is 
     begin 
     self.total := self.total || ',' || value; 
     return ODCIConst.Success; 
     end; 

     member function ODCIAggregateTerminate(self IN rmd_agg_type, 
              returnValue OUT clob, 
              flags IN number) 
     return number 
     is 
     begin 
     returnValue := ltrim(self.total,','); 
     return ODCIConst.Success; 
     end; 

     member function ODCIAggregateMerge(self IN OUT rmd_agg_type, 
             ctx2 IN rmd_agg_type) 
     return number 
     is 
     begin 
     self.total := self.total || ctx2.total; 
     return ODCIConst.Success; 
     end; 

    end; 
    /

    CREATE or replace 
    FUNCTION stragg_clob(input varchar2) 
    RETURN clob 
    PARALLEL_ENABLE AGGREGATE USING rmd_agg_type; 
    /

    grant execute on stragg_clob to user_schema; 


    To mimic your scenario I created two table and used it below-populated 2million records and then update the destination table CLOB column by appending values. 


    create table seed_values (name1 varchar2(10), col2 varchar2(250)); 

    insert into seed_values 
    select 'TMP'||level, 'ADI'||level from dual connect by level<2000000; 

    commit; 

    create table clob_value (base_data clob); 

    insert into clob_value values ('Value from before seed data#'); 

    commit; 
    update clob_value set base_data = base_data || (
                select sys.stragg_clob(name1||','||col2) as enames from seed_values 
                ); 
+0

上面給出的代碼適用於他,但不幸的是沒有在我的分貝上有太大的區別 – Alwyn