2013-06-03 24 views
7

我目前正在开始一个项目,我必须根据数据库中的多个表编写代码(pl/sql)来导出大型XML文件。从oracle生成大型xml文件:最佳实践

导出文件可能会变得相当大,可能包含多达700.000个客户(包括他们的地址,订单,电话号码等)。

我想知道是否有人对此有最佳方法的一些提示。我显然可以写出失去了XMLELEMENTS的选择,但这意味着整个文件将在内存中生成。

还有一个XML模式(XSD)可供文件必须符合。我还想知道是否有任何方法将表映射到XML模式。

任何提示将不胜感激。

+0

更适合dba.stackexchange.com –

+5

@BurhanKhalid不同意 - 这是一项开发任务,而不是数据库管理。 –

+0

其关于选择的最佳做法 - 我不明白这与dba.se * –

回答

5

XML有一些......在这方面的不足。正如你所看到的,大的XML文件可以像RAM和UNDO一样生存,就像没有明天一样。

我不诚实地相信存在一种叫做“最佳实践”的东西,这一切都取决于你自己的数据库,服务器和查询。但是,为了从大量(20?)的大表(10-400m行)写入大量(4.5GB)XML到磁盘,这是一个同事(我不能声称功劳)子查询。

  • 其实写出来的所有那些XMLElements

  • 如果您的SELECT语句是在所有复杂先创建一个表。

  • 从表中选择一个合理的元素,希望根据您的ID。例如,如果你有以下结构它将使意义它分割上<record>

    <someXML> 
        <record ID="1"> 
         <blah> 
          <moreBlah/> 
         </blah> 
        </record> 
        <record ID="2"> 
         <blah> 
          <moreBlah/> 
         </blah> 
        </record> 
    </someXML> 
    
  • 选中每条记录从数据库中CLOB。然后您将得到一系列将构成您的输出XML的CLOB。

  • 先编写打开标签然后单独或块,写每个CLOB磁盘

  • 确保您写信给本地磁盘。如果这是不可避免的写入网络共享,那里有一个很大的电缆指向它。您随后可以随时移动文件,这会比跨网络(或城市/国家/地区)大块写入效率更高。

  • 并行化!这并不总是可行的,但如果你能做到的话,那就做吧。

  • 小心并行化。您不希望编写格式不正确的XML。

我正在有效地倡导tbone的方法,而不是将它做成块。无论你做什么都避免把整个事情放在记忆中。

2

先尝试使用DBMS_XMLGEN。还有其它的方法为好,看到这个Oracle XML DB文档

DECLARE 
    v_ctx DBMS_XMLGEN.ctxhandle; 
    v_file UTL_FILE.file_type; 
    v_xml CLOB; 
    v_more BOOLEAN := TRUE; 
BEGIN 
    -- Create XML context. 
    v_ctx := DBMS_XMLGEN.newcontext('SELECT table_name, tablespace_name FROM user_tables WHERE rownum < 6'); 

    -- Set parameters to alter default Rowset and Row tag names and default case. 
    DBMS_XMLGEN.setrowsettag(v_ctx, 'USER_TABLES'); 
    DBMS_XMLGEN.setrowtag(v_ctx, 'TABLE'); 
    --DBMS_XMLGEN.settagcase(v_ctx, DBMS_XMLGen.LOWER_CASE); 

    -- Add an IE specfic XSL stylesheet reference so browser can transform the file. 
    --DBMS_XMLGEN.setstylesheetheader(v_ctx, 'C:\Development\XML\IEStyle.xsl', 'text/xsl'); 

    -- Create the XML document. 
    v_xml := DBMS_XMLGEN.getxml(v_ctx); 
    DBMS_XMLGEN.closecontext(v_ctx); 

    -- Output XML document to file. 
    v_file := UTL_FILE.fopen('C:\Development\XML\', 'test1.xml', 'w'); 
    WHILE v_more LOOP 
    UTL_FILE.put(v_file, SUBSTR(v_xml, 1, 32767)); 
    IF LENGTH(v_xml) > 32767 THEN 
     v_xml := SUBSTR(v_xml, 32768); 
    ELSE 
     v_more := FALSE; 
    END IF; 
    END LOOP; 
    UTL_FILE.fclose(v_file); 

    -- test insert into table 
    /* 
    insert into t_clob (clob_col) values (v_xml); 
    commit; 
    */ 
EXCEPTION 
    WHEN OTHERS THEN 
    DBMS_OUTPUT.put_line(Substr(SQLERRM,1,255)); 
    UTL_FILE.fclose(v_file); 
END; 

注意,我借这个最从优秀oracle-base网站

+0

嗨,你会请帮助我http://stackoverflow.com/questions/25279365/utl-file-write-error-when-calling-utl-file-put-in-a-loop? – Jaskey

0

另一个诀窍是将结果写入多个XML文件,即每个文件如10.000行,如Table_01_Rows_00001_99999.xml。然后在必要时合并XML文件。