Необходимо ли использовать DBMS_LOB при возврате CLOB из процедуры PL / SQL? - PullRequest
2 голосов
/ 23 октября 2009

Я хотел бы создать несколько процедур PL / SQL, которые возвращают XML в качестве параметров CLOB. Я хочу просто сделать это (что отлично работает с простыми тестами):

create or replace procedure p_xml_test_1(
  p_xml out nocopy clob
) is
begin
  p_xml := '<?xml version="1.0" encoding="utf8" ?>' ||
    '<test><something>some value</something></test>';
end p_xml_test_1;

Но у меня есть доступ к другому исходному коду, который в основном делает это:

create or replace procedure p_xml_test_2(
  p_xml out nocopy clob
) is
  lv_xml clob;
begin
  dbms_lob.createtemporary(
    lob_loc => p_xml,
    cache   => true
  );

  lv_xml := '<?xml version="1.0" encoding="utf8" ?>' ||
    '<test><something>some value</something></test>';

  dbms_lob.writeappend(
    lob_loc => p_xml,
    amount  => length(lv_xml),
    buffer  => lv_xml
  );
end p_xml_test_2;

Мне интересно, вызовет ли первый метод какие-либо проблемы для меня в будущем. Можно ли так делать? В чем преимущество второго метода? Спасибо!

Ответы [ 5 ]

1 голос
/ 26 октября 2009

Я провел следующие процедуры для сравнения времени выполнения:

Версия 1

create or replace procedure p_xml_test_1(
  p_xml out nocopy clob
) is
  lv_i number;
begin
  for lv_i in 1 .. 999999 loop
    p_xml := p_xml || 'a';
  end loop;
end p_xml_test_1;

Версия 2

create or replace procedure p_xml_test_2(
  p_xml out nocopy clob
) is
  lv_xml clob;
  lv_i   number;
begin
  dbms_lob.createtemporary(
    lob_loc => p_xml,
    cache   => true
  );

  for lv_i in 1 .. 999999 loop
    lv_xml := 'a';

    dbms_lob.writeappend(
      lob_loc => p_xml,
      amount  => length(lv_xml),
      buffer  => lv_xml
    );
  end loop;
end p_xml_test_2;

Разница незначительная. Оба приходят примерно на 0,2 секунды последовательно.

Если я переключу процедуры на цикл 999999 вместо 10000, производительность версии 1 начнет несколько снижаться (около 39 секунд против 32 секунд для версии 2).

0 голосов
/ 25 октября 2009

Есть еще один вариант, который вы не упомянули: использование встроенной в Oracle функциональности XML (при условии, что у вас версия базы данных 9i или выше). Например, генерация XML-документа из запроса - это фрагмент кода с DBMS_XMLGEN.getXML() или DBMS_XMLGEN.getXMLType().

0 голосов
/ 23 октября 2009

Я не вижу причин, почему вы хотели бы использовать второй.

Если lv_xml был VARCHAR2, а не CLOB, я вижу очень вескую причину (максимальная длина строкового литерала по сравнению с максимальной длиной CLOB).

0 голосов
/ 24 октября 2009

Спасибо за ответы. Исходя из того, что я прочитал на сайте, указанном ниже, я собираюсь предположить, что на самом деле полезно использовать dbms_lob.writeappend. Если я этого не сделаю, я мог бы также использовать VARCHAR2 (которых в некоторых случаях недостаточно).

Если у вас есть переменная CLOB с именем "l_clob", и вы делаете что-то вроде "l_clob: = l_clob || l_some_string_to_concatenate;", она преобразует значение l_clob с правой стороны уравнения в VARCHAR2 перед выполнением конкатенации , возможно, дает вам недействительные результаты или ошибку.

http://www.maristream.org/srea/Huge_Strings_Using_LOBs.htm

0 голосов
/ 23 октября 2009

Я думаю, вы должны измерить производительность обоих методов, запустив их много раз в цикле. Я думаю, что производительность - единственная разница. Ваш xml-блок короткий, но когда вы объединяете большой xml-блок, быстрее объединить его с dbms_low.writeappend, чем с помощью ||.

(По крайней мере, это было в Oracle 9, я думаю, что разница в производительности меньше в Oracle 10.)

...