私は、いくつかの変更を行った後、実行時間が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バイトです。
実行時間はわずかに増加するが、発生した大規模なジャンプは予想されませんでした。私は何を見落としましたか?
あなたがプロファイリングを見落としてきました。 [PL/SQL階層プロファイラ](https://docs.oracle.com/cd/B28359_01/appdev.111/b28424/adfns_profiler.htm)を参照してください。 – user272735
普通の古い 'dbms_profiler'は、すべての制限に対して、サーバにアクセスする必要なしに、どの行が時間を費やしているかを示します。私はそれが 'cell_write'(おそらく' case'ステートメントを使って組み合わせることができる)の複数の連結であると思います。そうでなければ、clobを読んだり、ファイルに書き込んだりしています。 (私はこれらすべての 'p_xml_body:= p_xml_body;'行にも困惑しています) –