【问题标题】:PL/SQL XMLType operation performancePL/SQL XMLType 操作性能
【发布时间】:2015-08-25 17:01:52
【问题描述】:

我有一个 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次。

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

【问题讨论】:

  • 对我来说看起来很简单。您说“函数”,但这只是一个选择语句。我假设您省略了一些代码?这个怎么称呼?
  • 你说你有一个需要 x 秒的函数,但你只向我们展示了一个 select 语句。你怎么知道 select 语句是瓶颈?恐怕你只是在猜测。
  • 当我说我有一个功能时,是因为我有......一个功能。该函数内的代码就是这个简单的选择语句。该函数的其余代码是 return lv_return 语句。就这么简单。是的......我已经衡量了这个声明的表现,如果我可以改变它,我现在想这样做。当然,我的流程中有越来越多的代码,但我不只是专注于此。

标签: oracle plsql xmltype


【解决方案1】:

结合 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 文档。这听起来很合理。一些简单的并行应该可以将时间从几小时缩短到几十分钟。

【讨论】:

  • 谢谢乔恩。但就我而言,我没有这个选项。这个函数在每个 XML 文档中调用一次。每个文档在此 IN_DATA 标记内只有一行。
猜你喜欢
  • 1970-01-01
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-28
  • 1970-01-01
  • 2010-11-02
  • 1970-01-01
相关资源
最近更新 更多