2010-04-29 40 views
1

我有一個系統正在對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中得到修復,但是我們沒有這些版本,並且由於沒有立即升級的計劃,我們必須對此進行編碼。

回答

2

正如我所提到的,它看起來像我們正在使用的軟件包中存在已知的內存問題,並且我使用的Oracle版本沒有應用修復程序。我發現我能夠在他們周圍編碼。

最初,我使用dbms_xmldom構建了一個XML文檔。我用SELECT(來自雙重語句)和XML函數替換了這段代碼:xmlelement,xmlconcat,xmlagg,xmlforest

要執行轉換,XMLType API有一個transform函數,我用這個函數代替dbms_xslprocessor包。它運行速度較慢,但​​似乎更加一致(速度和內存使用情況),並且在系統內存不足時不會崩潰。 :)

1

我的理解是,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