Oracle PL\SQL XMLTable性能
我有一个解析XMLTYPE变量的函数,对于每条消息,为XMLTYPE变量中的每个标记附加一个具有特定结构的CLOB。 像这样:Oracle PL\SQL XMLTable性能,oracle,plsql,xmltype,Oracle,Plsql,Xmltype,我有一个解析XMLTYPE变量的函数,对于每条消息,为XMLTYPE变量中的每个标记附加一个具有特定结构的CLOB。 像这样: FUNCTION myFunc (px_Header IN VARCHAR2, px_Block IN XMLTYPE, pn_numLines OUT PLS_INTEGER) RE
FUNCTION myFunc (px_Header IN VARCHAR2,
px_Block IN XMLTYPE,
pn_numLines OUT PLS_INTEGER)
RETURN CLOB
IS
lcl_return CLOB := EMPTY_CLOB;
BEGIN
pn_numLines := 0;
FOR item
IN ( SELECT RPAD (NVL (RECEIPTNUMBER, ' '), 20) AS RECEIPTNUMBER,
RPAD (NVL (COMPANYCODE, ' '), 3) AS COMPANYCODE,
RPAD (NVL (BRAND, ' '), 3) AS BRAND,
RPAD (NVL (POLICYNUMBER, ' '), 20) AS POLICYNUMBER,
RPAD (NVL (CLAIMNUMBER, ' '), 20) AS CLAIMNUMBER,
RECEIPTAMOUNT
AS receiptAmount
FROM XMLTABLE (
'INT_DATA/Item'
PASSING px_Block
COLUMNS RECEIPTNUMBER VARCHAR2 (20)
PATH 'RECEIPTNUMBER',
COMPANYCODE VARCHAR2 (3)
PATH 'COMPANYCODE',
BRAND VARCHAR2 (3) PATH 'BRAND',
POLICYNUMBER VARCHAR2 (20)
PATH 'POLICYNUMBER',
CLAIMNUMBER VARCHAR2 (20)
PATH 'CLAIMNUMBER',
RECEIPTAMOUNT VARCHAR2 (15)
PATH 'RECEIPTAMOUNT'))
LOOP
lcl_return:=
lcl_return
|| px_Header
|| 'B2'
|| item.RECEIPTNUMBER
|| item.COMPANYCODE
|| item.BRAND
|| item.POLICYNUMBER
|| item.CLAIMNUMBER
|| item.RECEIPTAMOUNT
|| CHR (13)
|| CHR (10);
pn_numLines := pn_numLines + 1;
END LOOP;
RETURN lcl_return;
END myFunc ;
如果我有一个小的px\u块
,这会很好地工作。但我有一个例子,我可以有一个大的XMLTYPE,这个函数需要很长时间。
我是新使用XMLType和XMLTable的。我能做些什么来提高绩效吗。也许使用批量收集语句
提前感谢,,
菲利佩
编辑1:
这里有一个仅用于两个实例的XML示例
<INT_DATA>
<Item>
<RECEIPTNUMBER>1</RECEIPTNUMBER>
<COMPANYCODE>148</COMPANYCODE>
<BRAND>006</BRAND>
<POLICYNUMBER>72972</POLICYNUMBER>
<CLAIMNUMBER>2015101504</CLAIMNUMBER>
<RECEIPTAMOUNT>-10.00</RECEIPTAMOUNT>
</Item>
<Item>
<RECEIPTNUMBER>1</RECEIPTNUMBER>
<COMPANYCODE>148</COMPANYCODE>
<BRAND>006</BRAND>
<POLICYNUMBER>73785</POLICYNUMBER>
<CLAIMNUMBER>2015101505</CLAIMNUMBER>
<RECEIPTAMOUNT>-22.50</RECEIPTAMOUNT>
</Item>
</INT_DATA>
由于XML表示一个简单的表结构,因此可以使用dbms_xmlsave将XML数据存储在表中
declare
l_clob clob;
l_rows number;
l_insctx dbms_xmlsave.ctxtype;
begin
l_clob := '<INT_DATA>
<Item>
<RECEIPTNUMBER>1</RECEIPTNUMBER>
<COMPANYCODE>148</COMPANYCODE>
<BRAND>006</BRAND>
<POLICYNUMBER>72972</POLICYNUMBER>
<CLAIMNUMBER>2015101504</CLAIMNUMBER>
<RECEIPTAMOUNT>-10.00</RECEIPTAMOUNT>
</Item>
<Item>
<RECEIPTNUMBER>1</RECEIPTNUMBER>
<COMPANYCODE>148</COMPANYCODE>
<BRAND>006</BRAND>
<POLICYNUMBER>73785</POLICYNUMBER>
<CLAIMNUMBER>2015101505</CLAIMNUMBER>
<RECEIPTAMOUNT>-22.50</RECEIPTAMOUNT>
</Item>
</INT_DATA>';
l_insctx := dbms_xmlsave.newcontext('TEST');
dbms_xmlsave.setrowtag(l_insctx, 'Item');
l_rows := dbms_xmlsave.insertxml(l_insctx, l_clob);
dbms_xmlsave.closecontext(l_insctx);
end;
首先创建一个与XML数据匹配的表
-- Create table
create table TEST
(
receiptnumber NUMBER,
companycode NUMBER,
brand VARCHAR2(10),
policynumber NUMBER,
claimnumber NUMBER,
receiptamount NUMBER
)
然后使用dbms_xmlsave将数据存储在表中
declare
l_clob clob;
l_rows number;
l_insctx dbms_xmlsave.ctxtype;
begin
l_clob := '<INT_DATA>
<Item>
<RECEIPTNUMBER>1</RECEIPTNUMBER>
<COMPANYCODE>148</COMPANYCODE>
<BRAND>006</BRAND>
<POLICYNUMBER>72972</POLICYNUMBER>
<CLAIMNUMBER>2015101504</CLAIMNUMBER>
<RECEIPTAMOUNT>-10.00</RECEIPTAMOUNT>
</Item>
<Item>
<RECEIPTNUMBER>1</RECEIPTNUMBER>
<COMPANYCODE>148</COMPANYCODE>
<BRAND>006</BRAND>
<POLICYNUMBER>73785</POLICYNUMBER>
<CLAIMNUMBER>2015101505</CLAIMNUMBER>
<RECEIPTAMOUNT>-22.50</RECEIPTAMOUNT>
</Item>
</INT_DATA>';
l_insctx := dbms_xmlsave.newcontext('TEST');
dbms_xmlsave.setrowtag(l_insctx, 'Item');
l_rows := dbms_xmlsave.insertxml(l_insctx, l_clob);
dbms_xmlsave.closecontext(l_insctx);
end;
声明
l_clob clob;
l_行数;
l_insctx dbms_xmlsave.ctxtype;
开始
l_clob:='
1.
148
006
72972
2015101504
-10.00
1.
148
006
73785
2015101505
-22.50
';
l_insctx:=dbms_xmlsave.newcontext('TEST');
setrowtag(l_insctx,'Item');
l_行:=dbms_xmlsave.insertxml(l_insctx,l_clob);
dbms_xmlsave.closecontext(l_insctx);
结束;
也许这会更好。XMLTABLE的问题在于Oracle使用a来读取XML。这意味着整个XML必须以很大的开销加载到内存中。看一看。此包使用基于事件(或基于流)的 使用SAX解析器,您可以在普通PC上读取大小为几GB的XML文件
但是,在—比方说50-100兆字节—之前,DOM解析器应该可以正常工作。我已经找到了问题并解决了它。 正如@Rene所说,延迟不在XML解析器中,而是在CLOB追加中 使用“| |”将varchar2追加到CLOB需要很长时间。因此,我需要使用DBMS_LOB.append。但要做到这一点,我需要在CLOB中找到一些东西。我不能附加到空CLOB 这就是为什么我要解决这个问题:
FUNCTION myFunc (px_Header IN VARCHAR2,
px_Block IN XMLTYPE,
pn_numLines OUT PLS_INTEGER)
RETURN CLOB
IS
lcl_return CLOB;
v_tmpVarchar VARCHAR2 (32000);
lv_line VARCHAR2 (32000);
BEGIN
pn_numLines := 0;
FOR item
IN ( SELECT RPAD (NVL (RECEIPTNUMBER, ' '), 20) AS RECEIPTNUMBER,
RPAD (NVL (COMPANYCODE, ' '), 3) AS COMPANYCODE,
RPAD (NVL (BRAND, ' '), 3) AS BRAND,
RPAD (NVL (POLICYNUMBER, ' '), 20) AS POLICYNUMBER,
RPAD (NVL (CLAIMNUMBER, ' '), 20) AS CLAIMNUMBER,
RECEIPTAMOUNT
AS receiptAmount
FROM XMLTABLE (
'INT_DATA/Item'
PASSING px_Block
COLUMNS RECEIPTNUMBER VARCHAR2 (20)
PATH 'RECEIPTNUMBER',
COMPANYCODE VARCHAR2 (3)
PATH 'COMPANYCODE',
BRAND VARCHAR2 (3) PATH 'BRAND',
POLICYNUMBER VARCHAR2 (20)
PATH 'POLICYNUMBER',
CLAIMNUMBER VARCHAR2 (20)
PATH 'CLAIMNUMBER',
RECEIPTAMOUNT VARCHAR2 (15)
PATH 'RECEIPTAMOUNT'))
LOOP
lv_line :=
px_Header
|| 'B2'
|| item.RECEIPTNUMBER
|| item.COMPANYCODE
|| item.BRAND
|| item.POLICYNUMBER
|| item.CLAIMNUMBER
|| item.RECEIPTAMOUNT
|| CHR (13)
|| CHR (10);
pn_numLines := pn_numLines + 1;
appendCLOB (lcl_retorno, lv_tmpVarchar, lv_linha);
END LOOP;
RETURN lcl_return;
END myFunc ;
appendCLOB函数如下所示:
PROCEDURE appendCLOB (pcl_clob IN OUT NOCOPY CLOB,
pv_vc IN OUT NOCOPY VARCHAR2,
pv_text VARCHAR2)
IS
BEGIN
pv_vc := pv_vc || pv_text;
EXCEPTION
WHEN VALUE_ERROR
THEN
IF pcl_clob IS NULL
THEN
-- Add the first varchar
pcl_clob := pv_vc;
ELSE
-- If the clob is not empty, uses the DBMS_LOB.append function
DBMS_LOB.append (pcl_clob, pv_vc);
pv_vc := pv_text;
END IF;
END;
对于XML中的36k实例,我的函数只需不到一分钟的时间。
谢谢大家 什么是“大”和“长时间?”“大”是指XML中主标记的35k个实例。“长时间”指超过2小时。:)好啊那又大又慢!您能给出一个简单、完整的XML示例吗?pkg_sap_fscd.formatamoEdattxt函数做什么?是占用时间的XML处理还是循环中的CLOB连接?在不执行任何代码的情况下尝试循环。@Rene您是对的。这是一个CLOB追加问题。没有它,需要48秒。你好,雷内,谢谢。但我不想用临时桌子来做这个。