从oracle生成大型xml文件:最佳实践

时间:2013-06-03 13:05:38

标签: oracle plsql

我目前正在开始一个项目,我将不得不根据数据库中的几个表编写代码(pl / sql)来导出大型XML文件。

导出文件可能会变得非常大,最多可能包含700,000个客户(包括他们的地址,订单,电话号码等)。

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

还有一个XML架构(XSD)可供文件必须遵守。我还想知道是否有任何方法可以将表“映射”到XML模式。

任何提示都表示赞赏。

3 个答案:

答案 0 :(得分:6)

XML在这方面有一些......缺点。正如您所注意到的那样,大型XML文件可能会占用RAM和UNDO,就像明天一样。

我并不诚实地相信那些被称为“最佳实践”的东西。存在,这一切都取决于您自己的数据库,服务器和查询。然而,这就是为了从大量(20?)的大型磁盘中将大量(4.5GB)的XML写入磁盘,我刚才所做的事情(我无法申请信用)表(10-400m行),具有极其复杂的子查询。

  • 实际上写出所有这些XMLElements

  • 如果您的SELECT语句完全复杂,请先创建一个表。

  • 从表中选择,采取合理的元素,希望根据您的ID。例如,如果您具有以下结构,则将其拆分为<record>

    是有意义的

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

  • 首先单独写入开始标记,或者以块的形式写入每个CLOB到磁盘

  • 确保您在本地写入磁盘。如果它无法避免写入网络共享,那里有一条巨大的电缆指向它。您随后可以随时移动文件,这比以网络形式在网络(或城市/国家/地区)内写作更有效。

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

  • 小心并行化。你不想写错误的XML。

我有效地提倡tbone的方法,而不是以块的形式进行。无论你做什么都避免将整件事放在记忆中。

答案 1 :(得分:3)

首先尝试使用DBMS_XMLGEN。还有其他方法,请参阅此Oracle XML DB doc

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网站

中借用了大部分内容

答案 2 :(得分:0)

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