Создание больших xml-файлов из oracle: рекомендации

в настоящее время я начинаю работу над проектом, где мне нужно будет написать код (pl/sql) для экспорта больших XML-файлов на основе нескольких таблиц в базе данных.

файлы экспорта могут стать довольно большими и могут содержать до 700.000 клиентов (с их адресами, заказами, номерами телефонов и т. д..).

Мне было интересно, есть ли у кого-нибудь советы по лучшему подходу к этому. Я мог бы, очевидно, просто написать selects с потерянными XMLELEMENTS в них, но это это означает, что весь файл будет сгенерирован в памяти.

также доступна XML-схема (XSD), которой должны соответствовать файлы. Мне также было интересно, есть ли способ "сопоставить" таблицу со схемой XML.

любые советы приветствуются.

3 ответов


XML имеет некоторые... недостатки в этой области. Большие XML-файлы, как вы заметили, могут hog RAM и отменить, как будто завтра нет.

Я честно не верю, что существует что-то под названием "Лучшие практики", все зависит от вашей собственной базы данных, сервера и запросов. Однако вот что сделал коллега (я не могу претендовать на кредит), чтобы написать огромные суммы (4,5 ГБ) XML на диск из большого числа (20?) больших таблиц (10-400М строк) с весьма сложным вложенный запрос.

  • фактически выпишите все эти XMLElements

  • Если ваша инструкция SELECT вообще сложна, сначала создайте таблицу.

  • выберите из таблицы, принимая разумный элемент, надеюсь, на основе вашего идентификатора. Например, если у вас есть следующая структура, имеет смысл разделить ее на <record>

    <someXML>
        <record ID="1">
            <blah>
                <moreBlah/>
            </blah>
        </record>
        <record ID="2">
            <blah>
                <moreBlah/>
            </blah>
        </record>
    </someXML>
    
  • выберите каждую запись как CLOB из база данных. Затем вы получите серию Клобов, которые будут составлять ваш выходной XML.

  • Сначала напишите открывающий тег, затем индивидуально или кусками, напишите каждый клоб на диск

  • убедитесь, что вы пишете на диск локально. Если этого нельзя избежать, напишите в сетевой ресурс, где есть большой толстый кабель, указывающий на него. Вы всегда можете переместить свой файл после этого, и это будет более эффективно, чем запись по сети (или городу/стране) в куски.

  • распараллелить! Это не всегда возможно, но если вы можете это сделать, сделайте это.

  • будьте осторожны с распараллеливанием. Вы не хотите писать искаженный XML.

Я эффективно пропагандирую подход tbone, вместо этого не делайте этого кусками. Что бы вы ни делали, старайтесь не заносить все это в память.


сначала попробуйте использовать 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;

обратите внимание, что я позаимствовал большую часть этого из excellent oracle-base сайт


другой трюк-запись результатов в несколько XML-файлов, то есть, скажем, 10.000 строк на файл, такой как Table_01_Rows_00001_99999.XML. Затем при необходимости объедините XML-файлы позже.