2015-08-25 33 views
0

我有一個PL/SQL函數來解析我的XML塊並將其返回到變量VARCHAR。 我的XML塊不是太複雜。只有14個標籤,並沒有任何重複結構。 在我的功能我做了這個手術的XMLType:PL/SQL 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

看起來很簡單。你說,「功能」,但這只是一個選擇語句。我假設你已經省略了一些代碼?這是如何被稱爲? – OldProgrammer

+0

你說你有一個函數需要x秒,但然後你只給我們一個選擇語句。你怎麼知道select語句是瓶頸?恐怕你只是在猜測。 – user272735

+0

當我說我有一個功能,是因爲我有一個功能。該函數內的代碼就是這個簡單的select語句。該函數的其餘代碼是返回lv_return語句。就這樣。是的,我已經衡量了這個聲明的表現,我想現在如果我可以改變它。當然,我的程序中有越來越多的代碼,但不是我只專注於此。 – milheiros

回答

0

結合XML並處理一個大文檔而不是許多小文檔。這至少可以減少SQL和PL/SQL之間的上下文切換次數,並且可能允許Oracle利用其他效率。

代替處理的一個排-AT-A-時間:

<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 

EDIT

如果文件不能被組合,並且如果輸入的字符串相對簡單,並且可以被信任,以字符串函數替換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文檔。這聽起來很合理。一些簡單的並行性應該能夠將時間從幾小時縮短到幾十分鐘。

+0

謝謝喬恩。但在我的情況下,我沒有這個選項。這個函數被稱爲每個XML文檔一次。每個文檔在這個IN_DATA標籤中只有一行。 – milheiros