2016-08-19 7 views
0

私は、いくつかの変更を行った後、実行時間が30分から3時間になったため、パフォーマンスを改善する方法を特定できませんでした。 プログラムは、Excelで使用するために、元々はcsvファイルを出力していました。プログラムは、Excelで使用するためにXMLを出力するように変更されました。 したがって、SQLまたはデータベースの読み取りに関するコードの変更はありません。 関連するコードの追加は、関連するパッケージから取得されたプロシージャで、clobをビルドし、定期的にファイルに出力するため、過剰なメモリ使用を避けることができます。 utl_file.put_lineの使用数は、両方のバージョンのプログラムで似ています。PL/SQL CPUパフォーマンスチューニング

CLOBを構築するために使用されるコードの例は、出力が

PROCEDURE write_file(p_filename IN VARCHAR2, 
        p_dir   IN VARCHAR2, 
        p_file_handle IN utl_file.file_type, 
        p_clob  IN CLOB) 
    IS 

c_amount CONSTANT BINARY_INTEGER := 32767; 
l_buffer VARCHAR2(32767); 
l_chr10 PLS_INTEGER; 
l_cloblen PLS_INTEGER; 
l_fhandler utl_file.file_type; 
l_pos  PLS_INTEGER := 1; 

BEGIN 

l_cloblen := dbms_lob.getlength(p_clob); 

WHILE l_pos < l_cloblen 
LOOP 
    l_buffer := dbms_lob.substr(p_clob, c_amount, l_pos); 
    EXIT WHEN l_buffer IS NULL; 
    l_chr10 := instr(l_buffer, chr(10), -1); 

    IF l_chr10 != 0 THEN 
    l_buffer := substr(l_buffer, 1, l_chr10 - 1); 
    END IF; 
    DBMS_OUTPUT.PUT_LINE('Buffer Length ' || LENGTH(l_buffer)) ; 
    DBMS_OUTPUT.PUT_LINE(l_buffer) ; 
    utl_file.put_line(p_file_handle, l_buffer, TRUE); 
    l_pos := l_pos + least(length(l_buffer) + 1, c_amount); 
END LOOP; 

EXCEPTION 
WHEN OTHERS THEN 
    DBMS_OUTPUT.PUT_LINE('Buffer Length ' || LENGTH(l_buffer)) ; 
    DBMS_OUTPUT.PUT_LINE(l_buffer) ; 
    IF utl_file.is_open(l_fhandler) THEN 
    utl_file.fclose(l_fhandler); 
    END IF; 
    RAISE; 
END; 

で書き込むためのコードとサンプルコール

PROCEDURE cell_write(p_xml_body IN OUT NOCOPY CLOB, 
        p_data_type IN   VARCHAR2 := 'String', 
        p_style_id IN   VARCHAR2 := NULL, 
        p_merge  IN   VARCHAR2 := NULL, 
        p_formula IN   VARCHAR2 := NULL, 
        p_line_feed IN   BOOLEAN := TRUE, 
        p_content IN   VARCHAR2) IS  
    v_line_feed VARCHAR2(01) ;      
BEGIN 
    IF p_line_feed 
    THEN 
     v_line_feed := chr(10) ; 
    ELSE 
     v_line_feed := ' ' ; 
    END IF ; 
    p_xml_body := p_xml_body || ' <Cell'; 
    IF p_merge IS NULL 
    THEN 
     p_xml_body := p_xml_body ; 
    ELSE 
     p_xml_body := p_xml_body || ' ss:MergeAcross="' || p_merge || '"' ; 
    END IF ; 
    IF p_style_id IS NULL 
    THEN 
     p_xml_body := p_xml_body ; 
    ELSE 
     p_xml_body := p_xml_body || ' ss:StyleID="'||p_style_id||'"' ; 
    END IF; 
    IF p_formula IS NULL 
    THEN 
     p_xml_body := p_xml_body ; 
    ELSE 
     p_xml_body := p_xml_body || ' ss:Formula="'||p_formula||'"' ; 
    END IF; 
    p_xml_body := p_xml_body || '><Data ss:Type="'||p_data_type||'">' ||     P_content || '</Data></Cell>' || v_line_feed; 
END cell_write; 

ある手順cell_writeが

pk_create_excel_workbook.cell_write(p_xml_body =>v_clob_term, 
            p_line_feed => FALSE, 
            p_data_type =>'Number', 
            p_style_id =>'s94', 
            p_content  =>w_totemployeecontribT); 

あります出力回線あたり約100回、約30,000出力回線と呼ばれます。出力ラインは通常8000〜10000バイトです。

実行時間はわずかに増加するが、発生した大規模なジャンプは予想されませんでした。私は何を見落としましたか?

+1

あなたがプロファイリングを見落としてきました。 [PL/SQL階層プロファイラ](https://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns_profiler.htm)を参照してください。 – user272735

+0

普通の古い 'dbms_profiler'は、すべての制限に対して、サーバにアクセスする必要なしに、どの行が時間を費やしているかを示します。私はそれが 'cell_write'(おそらく' case'ステートメントを使って組み合わせることができる)の複数の連結であると思います。そうでなければ、clobを読んだり、ファイルに書き込んだりしています。 (私はこれらすべての 'p_xml_body:= p_xml_body;'行にも困惑しています) –

答えて

0

私の推測では、複数の連結がcell_writeになります。 (。プロファイリングが確認されます)

を理想的にではなく、このように手動でタグを連結するよりも、提供されたXMLインターフェイスツールを使用することになり、とにかくクイックフィックスとして私が(未テスト)は、このような何かをしようとするだろう:

procedure cell_write 
    (p_xml_body in out nocopy clob 
    , p_data_type in varchar2 := 'String' 
    , p_style_id in varchar2 := null 
    , p_merge  in varchar2 := null 
    , p_formula in varchar2 := null 
    , p_line_feed in boolean := true 
    , p_content in varchar2) 
is 
    k_line_feed constant varchar2(1) := case when p_line_feed then chr(10) else ' ' end; 
begin 
    p_xml_body := p_xml_body || 
     ' <Cell' || 
     case when p_merge is not null then ' ss:MergeAcross="' || p_merge || '"' end || 
     case when p_style_id is not null then ' ss:StyleID="' || p_style_id || '"' end || 
     case when p_formula is not null then ' ss:Formula="' || p_formula || '"' end || 
     '><Data ss:Type="' || p_data_type || '">' || p_content || '</Data></Cell>' || 
     k_line_feed; 
end cell_write; 
+0

おかげさまで私は実験をして得たものを見ています – Jaffa6

+0

コメントありがとう、私はDBMSプロファイリングの使い方に慣れていませんでした。プログラムを30分に戻しました。常にCLOBに連結することは非常に非効率的なようです。 – Jaffa6

0

私が長年使用してきたアプローチの1つは、の追加を実行する前に、 varchar2ステートフルPL/SQLという変数をバッファとして使用して作業することです。そして私はコアDBMS_LOBの周りにシンプルなAPIを作成して、いつでも複数のCLOBに書き込んだり、必要に応じてそれらの間を交互に書き込んだりできます。あなたは多分あなたはより良い性能を達成することができ、それを見てとることができます。

https://github.com/GeraldoViana/nksg/blob/master/src/nksg_tempclob.pks https://github.com/GeraldoViana/nksg/blob/master/src/nksg_tempclob.pkb

+0

このリンクは質問に答えるかもしれませんが、答えの本質的な部分をここに含めて参考にしてください。リンクされたページが変更された場合、リンクのみの回答は無効になります。 - [レビューから](/レビュー/低品質の投稿/ 18329433) – Sree

関連する問題