我有一个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次。
有没有更快的方法来实现这一点来改善,即使只有几千分之一秒?
答案 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文档。这听起来很合理。一些简单的并行性应该能够将时间从几小时缩短到几十分钟。