PL / SQL XMLType操作性能

时间:2015-08-25 17:01:52

标签: oracle plsql xmltype

我有一个PL / SQL函数来解析我的XML块并将其返回到VARCHAR变量。 我的XML块不是太复杂。只有14个标签,没有任何重复结构。 在我的函数中,我做了这个XMLType操作:

SELECT    px_Header
                               || 'R5'
                               || RPAD (NVL (A1, ' '), 2)
                               || RPAD (NVL (A2, ' '), 10)
                               || RPAD (NVL (A3, ' '), 3)
                               || RPAD (NVL (A4, ' '), 1)
                               || RPAD (NVL (A5, ' '), 1)
                               || RPAD (NVL (A6, ' '), 10)
                               || RPAD (NVL (A7, ' '), 1)
                               || RPAD (NVL (A8, ' '), 8)
                               || RPAD (NVL (A9, ' '), 1)
                               || RPAD (NVL (A10, ' '), 16)
                               || RPAD (NVL (A11, ' '), 2)
                               || RPAD (NVL (A12, ' '), 8)
                               || RPAD (NVL (A13, ' '), 1)
                               || RPAD (NVL (A14, ' '), 1)
                               || CHR (13)
                               || CHR (10)
                          INTO lv_return
                          FROM XMLTABLE (
                                  '/IN_DATA'
                                  PASSING px_Block
                                  COLUMNS A1          VARCHAR2 (2) PATH 'A1',
                                          A2       VARCHAR2 (10)
                                                                     PATH 'A2',
                                          A3             VARCHAR2 (3) PATH 'A3',
                                          A4             VARCHAR2 (1) PATH 'A4',
                                          A5     VARCHAR2 (1)
                                                                     PATH 'A5',
                                          A6       VARCHAR2 (10)
                                                                     PATH 'A6',
                                          A7         VARCHAR2 (1)
                                                                     PATH 'A7',
                                          A8              VARCHAR2 (8) PATH 'A8',
                                          A9    VARCHAR2 (1)
                                                                     PATH 'A9',
                                         A10             VARCHAR2 (16)
                                                                     PATH 'A10',
                                          A11          VARCHAR2 (2)
                                                                     PATH 'A11',
                                          A12          VARCHAR2 (8)
                                                                     PATH 'A12',
                                          A13   VARCHAR2 (1)
                                                                     PATH 'A13',
                                          A14         VARCHAR2 (1)
                                                                     PATH 'A14');

此功能需要0.0945秒才能执行。我认为并非如此。但我的过程需要迭代100000次,所以我称这个函数为100000次。

有没有更快的方法来实现这一点来改善,即使只有几千分之一秒?

1 个答案:

答案 0 :(得分:0)

结合XML并处理一个大文档而不是许多小文档。这至少减少了SQL和PL / SQL之间的上下文切换量  可能也允许Oracle利用其他效率。

而不是一次处理一行:

<IN_DATA><A1>1</A1><A2>2</A2></IN_DATA>

处理多行:

<ALL_DATA>
    <IN_DATA><A1>1</A1><A2>2</A2></IN_DATA>
    <IN_DATA><A1>3</A1><A2>4</A2></IN_DATA>
</ALL_DATA>

使用这样的代码:

--Process XML.
declare
    v_strings sys.odcivarchar2list;
    px_Block xmltype := xmltype('
        <ALL_DATA>
            <IN_DATA><A1>1</A1><A2>2</A2></IN_DATA>
            <IN_DATA><A1>3</A1><A2>4</A2></IN_DATA>
        </ALL_DATA>');
begin
    --Get strings.
    select A1||' '||A2
    bulk collect into v_strings
    from
    xmltable
    (
        '/ALL_DATA/IN_DATA' passing px_Block columns
        a1 varchar2 (2)  path 'A1',
        a2 varchar2 (10) path 'A2'
    );

    --Display strings for testing.
    for i in 1 .. v_strings.count loop
        dbms_output.put_line(v_strings(i));
    end loop;
end;
/

结果:

1 2
3 4

修改

如果文档无法组合,并且输入字符串相对简单且可信任,则使用字符串函数替换XML处理可以显着提高性能。

下面的示例使用较小的输入字符串,但是从XML更改为字符串处理会将时间从30秒缩短到几乎没有。

--Process XML.
declare
    v_result varchar2(100);
    v_xml xmltype := xmltype('<IN_DATA><A1>1</A1><A2>2</A2></IN_DATA>');
    v_string varchar2(100) := '<IN_DATA><A1>1</A1><A2>2</A2></IN_DATA>';

    function get_string_from_xml(p_xml xmltype) return varchar2 is
        v_string varchar2(100);
    begin
        --Get strings.
        select A1||' '||A2
        into v_string
        from
        xmltable
        (
            '/IN_DATA' passing v_xml columns
            a1 varchar2 (2)  path 'A1',
            a2 varchar2 (10) path 'A2'
        );
        return v_string;
    end get_string_from_xml;

    function get_string_from_string(p_string varchar2) return varchar2 is
        v_string varchar2(100);
    begin
        return
            substr(p_string, instr(p_string, '<A1>') + 4, instr(p_string, '</A1>') - instr(p_string, '<A1>') - 4)
            ||' '||
            substr(p_string, instr(p_string, '<A2>') + 4, instr(p_string, '</A2>') - instr(p_string, '<A2>') - 4);
    end get_string_from_string;

begin
    --27 seconds
/*
    for i in 1 .. 100000 loop
        v_result := get_string_from_xml(v_xml);
    end loop;
*/

    --0 seconds
    for i in 1 .. 100000 loop
        v_result := get_string_from_string(v_string);
    end loop;
end;
/

另一种看待这种情况的方法是,您的原始函数需要2.5小时才能使用单个线程处理100,000个XML文档。这听起来很合理。一些简单的并行性应该能够将时间从几小时缩短到几十分钟。