我有一个在XMLType对象上执行许多XSL转换的系统。问题是系统会随着时间的推移逐渐减慢,有时在内存不足时会崩溃。看起来减速(可能是内存崩溃)在dbms_xslprocessor.processXSL
函数调用周围,逐渐需要更长时间才能完成。
代码如下所示:
v_doc dbms_xmldom.DOMDocument;
v_transformer dbms_xmldom.DOMDocument;
v_XSLprocessor dbms_xslprocessor.Processor;
v_stylesheet dbms_xslprocessor.Stylesheet;
v_clob clob;
...
transformer := PKG_STUFF.getXSL();
v_transformer := dbms_xmldom.newDOMDocument(transformer);
v_XSLprocessor := Dbms_Xslprocessor.newProcessor;
v_stylesheet := dbms_xslprocessor.newStylesheet(v_transformer, '');
...
for source_data in (select id in source_tbl) loop
begin
v_doc := PKG_CONVERT.convert(in_id => source_data.id);
--start time of operation
v_begin_op_time := dbms_utility.get_time;
--reset the CLOB
v_clob := ' ';
--Apply XSL Transform
dbms_xslprocessor.processXSL(p => v_XSLprocessor, ss => v_stylesheet, xmldoc => v_Doc, cl => v_clob);
v_doc := dbms_xmldom.newDOMDocument(XMLType(v_clob));
--end time
v_end_op_time := dbms_utility.get_time;
--calculate duration
v_time_taken := (((v_end_op_time - v_begin_op_time)));
--log the duration
PKG_LOG.log_message('Time taken to transform XML: '||v_time_taken);
...
...
DBMS_XMLDOM.freeDocument(v_Doc);
DBMS_LOB.freetemporary(lob_loc => v_clob);
end loop;
转换XML所需的时间正在慢慢增加(我想它也可能是对dbms_xmldom.newDOMDocument的调用,但我认为这是相当简单的)。我不知道为什么.... :(
(Oracle 10g)
更新
通过简单地评论对processXSL
的调用进行的进一步测试似乎显着加快了速度。仍然在等待更大的数据集测试来确认这一点,但似乎processXSL
正在扼杀事情。有没有其他人有过这个问题?
我们现在没有转换许多XML文档,只有几千个。 XSL并不简单,但我只创建了一个Processor
,一个Transformer
和一个Stylesheet
,然后一遍又一遍地重复使用它们......
更新2:
即使没有转换,内存使用量也在不断增长。几乎不会崩溃,但它仍然不应该这样做。非常令人费解。
更新3:
所以......我们的DBA在dbms_xmldom
以及dbms_xslprocessor
中可能存在 已知内存泄漏的事实。问题已在较新版本的Oracle中得到修复,但我们没有这些版本,并且由于没有立即升级的计划,我们必须围绕此进行编码。
答案 0 :(得分:2)
正如我所提到的,看起来我们使用的软件包中存在已知的内存问题,而我使用的Oracle版本没有应用修复程序。我发现我能够围绕它们进行编码。
最初,我使用dbms_xmldom
来构建XML文档。我用SELECT(into ... from dual)语句和XML函数替换了这段代码:xmlelement
,xmlconcat
,xmlagg
,xmlforest
。
要执行转换,XMLType API具有transform
函数,我使用该函数代替dbms_xslprocessor
包。它运行速度较慢,但似乎更加一致(在速度和内存使用方面)并且在内存不足时不会使系统崩溃。 :)
答案 1 :(得分:1)
我的理解是,像XSL处理这样的DOM操作的内存使用往往是令牌数量的第四个幂。
我们还看到XML处理由于内存不足错误而失败 - 在XSL处理中,创建DOM文档等。
因此,我建议您在进行处理时检查DBA的手表内存使用情况并检查其缩放程度。
在我们的例子中,我们的XSL处理一次只需要在文档的相对较小的部分上进行操作。例如,我们提取了100,000个设施的数据,并且XSL在单个设施上转换了数据。通过以1000或5000的组进行处理然后将最终文档拼接在一起,我们能够大大加快速度并减少内存使用量。由于我们使用dbms_xmlgen.getXMLType()从关系表中提取数据来创建XML文档,因此我们可以使用dbms_xmlgen.setMaxRows来设置块大小。
其他语言的一些XSL处理器可以串行化并交换时间和空间以供内存使用。但是,据我所知,数据库版本希望将所有内容整合在一起并进行处理。