8

私は現在、データベース内のいくつかのテーブルに基づいて、大きな XML ファイルをエクスポートするコード (pl/sql) を作成する必要があるプロジェクトの作業を開始しています。

エクスポート ファイルは非常に大きくなる可能性があり、最大 700.000 人の顧客 (住所、注文、電話番号など) が含まれる可能性があります。

これに対する最善のアプローチについて誰かがヒントを持っているかどうか疑問に思っていました。もちろん、XMLELEMENTS が失われた select を書き出すこともできますが、それはファイル全体がメモリ内に生成されることを意味します。

ファイルが準拠する必要のある XML スキーマ (XSD) も利用できます。また、テーブルを XML スキーマに「マップ」する方法があるかどうかも疑問に思っていました。

どんなヒントでも大歓迎です。

4

3 に答える 3

6

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 のアプローチを効果的に提唱しています。何をするにしても、全体をメモリに入れることは避けてください。

于 2013-06-03T20:47:14.120 に答える
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サイトから借りたことに注意してください。

于 2013-06-03T20:37:26.207 に答える
0

もう 1 つのトリックは、結果を複数の XML ファイルに書き込むことです。つまり、Table_01_Rows_00001_99999.xml のように、ファイルごとに 10.000 行とします。その後、必要に応じて後で XML ファイルをマージします。

于 2016-02-09T18:40:45.867 に答える