大批量XSL操作导致Oracle性能问题

问题描述:

我有一个系统正在对XMLType对象执行许多XSL转换。问题在于随着时间的推移,系统逐渐变慢,有时会在内存不足时崩溃。看起来减速(可能是内存崩溃)是在dbms_xslprocessor.processXSL函数调用的周围,这需要更长,更长的时间才能完成。大批量XSL操作导致Oracle性能问题

的代码看起来是这样的:

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中)

UPDATE:

通过简单地调用注释掉到processXSL进一步的测试似乎显著加快速度仍在等待。对于较大的数据集测试来证实这一点,但似乎processXSL是什么真正让事情陷入困境。以前有没有其他人遇到过问题?

我们没有转换很多XML文档,现在只有几千个。 XSL不完全是imple,但我只有一个创造Processor,一个Transformer,和一个Stylesheet,然后一遍又一遍又一遍重复使用它们...

更新2:

即使没有转换,内存使用情况不断增长。几乎不会坏到崩溃,但它仍然不应该这样做。非常令人费解。

更新3:

所以......我们的DBA发现某处引用的事实有已知的内存泄漏dbms_xmldom,并可能在dbms_xslprocessor。问题在新版本的Oracle中得到修复,但是我们没有这些版本,并且由于没有立即升级的计划,我们必须对此进行编码。

正如我所提到的,它看起来像我们正在使用的软件包中存在已知的内存问题,并且我使用的Oracle版本没有应用修复程序。我发现我能够在他们周围编码。

最初,我使用dbms_xmldom构建了一个XML文档。我用SELECT(来自双重语句)和XML函数替换了这段代码:xmlelement,xmlconcat,xmlagg,xmlforest

要执行转换,XMLType API有一个transform函数,我用这个函数代替dbms_xslprocessor包。它运行速度较慢,但​​似乎更加一致(速度和内存使用情况),并且在系统内存不足时不会崩溃。 :)

我的理解是,DOM操作(如XSL处理)的内存使用往往会成为令牌数量的四倍。

我们也已经看到了XML处理,因为内存不足错误而失败 - 在XSL处理,创建DOM文档等

所以我推荐,而你做你的DBA的手表内存使用情况处理和检查它如何扩展。

在我们的案例中,我们的XSL处理只需要对文档中的一小部分进行操作。例如,我们正在提取100,000个工厂的数据,并将XSL数据转换为一个工厂。通过1000或5000组的处理,然后将最终文档拼接在一起,我们可以极大地加快速度并减少内存使用量。由于我们使用dbms_xmlgen.getXMLType()从关系表中提取数据来创建XML文档,因此我们可以使用dbms_xmlgen.setMaxRows来设置块大小。

其他语言中的某些XSL处理器序列化事物并交换时间和空间以供内存使用。但据我所知,数据库版本希望将所有内容整合到一起并对其进行处理。

+0

那么,您的过程听起来与我们的过程听起来很相似,因为我们有30,000个文档来提取数据,将XML放在一起,然后运行XSLT。是的,当我处理少于2000个文件时,内存问题并不太明显,但对于最终系统而言,停止和重新启动下一批2000年的过程并不是很可行。 – FrustratedWithFormsDesigner 2010-05-03 14:02:40

+0

@Jim Hudson:请参阅最近的更新和回复。 – FrustratedWithFormsDesigner 2010-05-03 14:12:01