将巨大的参数传递给 oracle 程序会影响性能吗?
Passing a huge parameter to oracle procedure have a performance hit?
我附上了一个脚本,我在其中尝试 process/parse XML in a table(STAGE_TBL) in XMLTYPE列并将解析后的数据插入另一个 table(PROCESSED_DATA_TBL)。 XML 最大可达 2MB,这会导致大约 2000 多行已解析数据。
我看到的问题是当我将 XML 对象传递给过程 (STAGE_TBL_PROCESS) 以解析它每 XML 大约需要 10 秒,而不是传递 XML如果我通过传递 ID 直接从过程 (STAGE_TBL_PROCESS) 中的 table 获取它,则大约需要 0.15 秒。
根据文档,所有 IN 参数均通过引用传递,那么为什么会出现这种性能差异?
数据库详细信息
Oracle 数据库 11g 企业版 11.2.0.3.0 版 - 64 位生产
PL/SQL 版本 11.2.0.3.0 - 生产
"CORE 11.2.0.3.0 Production"
Linux 的 TNS:版本 11.2.0.3.0 - 生产
NLSRTL 版本 11.2.0.3.0 - 生产
注意:我无法执行 SQL_TRACE 或 DBMS_STATS,因为我无权访问它们。
/*
This one is taking .15 seconds to process an XML with about 2000 rp_sendRow elements
*/
DECLARE
CURSOR NewStage IS
SELECT *
FROM STAGE_TBL
WHERE status = 'N'
ORDER BY PUT_TIME ASC;
SUBTYPE rt_NewStage IS NewStage % rowtype;
ROW_COUNT INTEGER := 0; -- Return value from calling the procedure
READ_COUNT INTEGER := 0; -- Number of rows read from the stage table
INSERT_COUNT_TOTAL INTEGER := 0; -- Number of Inserts Inven records
ERROR_COUNT INTEGER := 0; -- Number of Inven inserts that did inserted more then 1 row in Inven
PROCESS_STATUS STATUS.MmsStatus;
STATUS_DESCRIPTION STATUS.MmsStatusReason;
ERRMSG VARCHAR2(500);
PROCEDURE STAGE_TBL_PROCESS (IDDATA IN RAW, PROCESS_STATUS OUT VARCHAR2, STATUS_DESCRIPTION OUT VARCHAR2, ROW_COUNT OUT NUMBER) AS
/*
This procedure is to parse the XML from STAGE_TBL and populate the data from XML to PROCESSED_DATA_TBL table
IN PARAMS
----------
IDDATA - ID from STAGE_TBL
xData - XMLType field from XML_DOCUMENT of STAGE_TBL
OUT PARAMS
-----------
PROCESS_STATUS - The STATUS of parsing and populating PROCESSED_DATA_TBL
STATUS_DESCRIPTION - The description of the STATUS of parsing and populating PROCESSED_DATA_TBL
ROW_COUNT - Number of rows inserted into PROCESSED_DATA_TBL
*/
BEGIN
INSERT ALL INTO PROCESSED_DATA_TBL
(PD_ID,
STORE,
SALES_NBR,
UNIT_COST,
ST_FLAG,
ST_DATE,
ST,
START_QTY,
START_VALUE,
START_ON_ORDER,
HAND,
ORDERED,
COMMITED,
SALES,
RECEIVE,
VALUED,
ID_1,
ID_2,
ID_3,
UNIT_PRICE,
EFFECTIVE_DATE,
STATUS,
STATUS_DATE,
STATUS_REASON)
VALUES (IDDATA
,store
,SalesNo
,UnitCost
,StWac
,StDt
,St
,StartQty
,StartValue
,StartOnOrder
,Hand
,Ordered
,COMMITED
,Sales
,Rec
,Valued
,Id1
,Id2
,Id3
,UnitPrice
,to_Date(EffectiveDate||' '||EffectiveTime, 'YYYY-MM-DD HH24:MI:SS')
,'N'
,SYSDATE
,'XML PROCESS INSERT')
WITH T AS
( SELECT STG.XML_DOCUMENT FROM STAGE_TBL STG WHERE STG.ID = IDDATA)
-- This is to parse and fetch the data from XML
SELECT E.* FROM T, XMLTABLE('rp_send/rp_sendRow' PASSING T.XML_DOCUMENT COLUMNS
store VARCHAR(20) PATH 'store'
,SalesNo VARCHAR(20) PATH 'sales'
,UnitCost NUMBER PATH 'cost'
,StWac VARCHAR(20) PATH 'flag'
,StDt DATE PATH 'st-dt'
,St NUMBER PATH 'st'
,StartQty NUMBER PATH 'qty'
,StartValue NUMBER PATH 'value'
,StartOnOrder NUMBER PATH 'start-on-order'
,Hand NUMBER PATH 'hand'
,Ordered NUMBER PATH 'order'
,Commited NUMBER PATH 'commit'
,Sales NUMBER PATH 'sales'
,Rec NUMBER PATH 'rec'
,Valued NUMBER PATH 'val'
,Id1 VARCHAR(30) PATH 'id-1'
,Id2 VARCHAR(30) PATH 'id-2'
,Id3 VARCHAR(30) PATH 'id-3'
,UnitPrice NUMBER PATH 'unit-pr'
,EffectiveDate VARCHAR(30) PATH 'eff-dt'
,EffectiveTime VARCHAR(30) PATH 'eff-tm'
) E;
ROW_COUNT := SQL%ROWCOUNT; -- Not the # of all the rows inserted.
PROCESS_STATUS := STATUS.PROCESSED;
IF ROW_COUNT < 1 THEN -- The insert failed Row Count = 0 No exception thrown
PROCESS_STATUS := STATUS.ERROR;
STATUS_DESCRIPTION := 'ERROR Did not insert into Pos Inventory. Reason Unknown';
END IF;
EXCEPTION
WHEN OTHERS THEN
ROW_COUNT := 0;
PROCESS_STATUS := STATUS.ERROR;
STATUS_DESCRIPTION := 'SqlCode:' || SQLCODE || ' SqlErrMsg:' || SQLERRM;
END;
BEGIN
DBMS_OUTPUT.enable(NULL);
FOR A_NewStage IN NewStage
LOOP
READ_COUNT := READ_COUNT + 1;
STAGE_TBL_PROCESS(A_NewStage.ID, PROCESS_STATUS, STATUS_DESCRIPTION, ROW_COUNT);
INSERT_COUNT_TOTAL := INSERT_COUNT_TOTAL + ROW_COUNT;
IF(ROW_COUNT <= 0 OR PROCESS_STATUS = STATUS.ERROR) THEN
ERROR_COUNT := ERROR_COUNT + 1;
UPDATE STAGE_TBL
SET status = PROCESS_STATUS,
status_DATE = SYSDATE,
status_DESCRIPTION = STATUS_DESCRIPTION
WHERE ID = A_NewStage.ID;
ELSE
UPDATE STAGE_TBL
SET status = PROCESS_STATUS,
status_DATE = SYSDATE,
status_DESCRIPTION = STATUS_DESCRIPTION,
SHRED_DT = SYSDATE
WHERE ID = A_NewStage.ID;
END IF;
COMMIT;
END LOOP;
COMMIT;
IF ERROR_COUNT > 0 THEN
ERRMSG := '** ERROR: ' || ERROR_COUNT || ' Stage records did not insert in to the Processed table correctly';
RAISE_APPLICATION_ERROR(-20001,ErrMsg);
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END ;
/*
This one is taking 10 seconds to process an XML with about 2000 rp_sendRow elements
*/
DECLARE
CURSOR NewStage IS
SELECT *
FROM STAGE_TBL
WHERE status = 'N'
ORDER BY PUT_TIME ASC;
SUBTYPE rt_NewStage IS NewStage % rowtype;
ROW_COUNT INTEGER := 0; -- Return value from calling the procedure
READ_COUNT INTEGER := 0; -- Number of rows read from the stage table
INSERT_COUNT_TOTAL INTEGER := 0; -- Number of Inserts Inven records
ERROR_COUNT INTEGER := 0; -- Number of Inven inserts that did inserted more then 1 row in Inven
PROCESS_STATUS STATUS.MmsStatus;
STATUS_DESCRIPTION STATUS.MmsStatusReason;
ERRMSG VARCHAR2(500);
PROCEDURE STAGE_TBL_PROCESS (IDDATA IN RAW, xData IN STAGE_TBL.XML_DOCUMENT%TYPE, PROCESS_STATUS OUT VARCHAR2, STATUS_DESCRIPTION OUT VARCHAR2, ROW_COUNT OUT NUMBER) AS
/*
This procedure is to parse the XML from STAGE_TBL and populate the data from XML to PROCESSED_DATA_TBL table
IN PARAMS
----------
IDDATA - ID from STAGE_TBL
xData - XMLType field from XML_DOCUMENT of STAGE_TBL
OUT PARAMS
-----------
PROCESS_STATUS - The STATUS of parsing and populating PROCESSED_DATA_TBL
STATUS_DESCRIPTION - The description of the STATUS of parsing and populating PROCESSED_DATA_TBL
ROW_COUNT - Number of rows inserted into PROCESSED_DATA_TBL
*/
BEGIN
INSERT ALL INTO PROCESSED_DATA_TBL
(PD_ID,
STORE,
SALES_NBR,
UNIT_COST,
ST_FLAG,
ST_DATE,
ST,
START_QTY,
START_VALUE,
START_ON_ORDER,
HAND,
ORDERED,
COMMITED,
SALES,
RECEIVE,
VALUED,
ID_1,
ID_2,
ID_3,
UNIT_PRICE,
EFFECTIVE_DATE,
STATUS,
STATUS_DATE,
STATUS_REASON)
VALUES (IDDATA
,store
,SalesNo
,UnitCost
,StWac
,StDt
,St
,StartQty
,StartValue
,StartOnOrder
,Hand
,Ordered
,COMMITED
,Sales
,Rec
,Valued
,Id1
,Id2
,Id3
,UnitPrice
,to_Date(EffectiveDate||' '||EffectiveTime, 'YYYY-MM-DD HH24:MI:SS')
,'N'
,SYSDATE
,'XML PROCESS INSERT')
-- This is to parse and fetch the data from XML
SELECT E.* FROM XMLTABLE('rp_send/rp_sendRow' PASSING xDATA COLUMNS
store VARCHAR(20) PATH 'store'
,SalesNo VARCHAR(20) PATH 'sales'
,UnitCost NUMBER PATH 'cost'
,StWac VARCHAR(20) PATH 'flag'
,StDt DATE PATH 'st-dt'
,St NUMBER PATH 'st'
,StartQty NUMBER PATH 'qty'
,StartValue NUMBER PATH 'value'
,StartOnOrder NUMBER PATH 'start-on-order'
,Hand NUMBER PATH 'hand'
,Ordered NUMBER PATH 'order'
,Commited NUMBER PATH 'commit'
,Sales NUMBER PATH 'sales'
,Rec NUMBER PATH 'rec'
,Valued NUMBER PATH 'val'
,Id1 VARCHAR(30) PATH 'id-1'
,Id2 VARCHAR(30) PATH 'id-2'
,Id3 VARCHAR(30) PATH 'id-3'
,UnitPrice NUMBER PATH 'unit-pr'
,EffectiveDate VARCHAR(30) PATH 'eff-dt'
,EffectiveTime VARCHAR(30) PATH 'eff-tm'
) E;
ROW_COUNT := SQL%ROWCOUNT; -- Not the # of all the rows inserted.
PROCESS_STATUS := STATUS.PROCESSED;
IF ROW_COUNT < 1 THEN -- The insert failed Row Count = 0 No exception thrown
PROCESS_STATUS := STATUS.ERROR;
STATUS_DESCRIPTION := 'ERROR Did not insert into Pos Inventory. Reason Unknown';
END IF;
EXCEPTION
WHEN OTHERS THEN
ROW_COUNT := 0;
PROCESS_STATUS := STATUS.ERROR;
STATUS_DESCRIPTION := 'SqlCode:' || SQLCODE || ' SqlErrMsg:' || SQLERRM;
END;
BEGIN
DBMS_OUTPUT.enable(NULL);
FOR A_NewStage IN NewStage
LOOP
READ_COUNT := READ_COUNT + 1;
STAGE_TBL_PROCESS(A_NewStage.ID, A_NewStage.XML_DOCUMENT, PROCESS_STATUS, STATUS_DESCRIPTION, ROW_COUNT);
INSERT_COUNT_TOTAL := INSERT_COUNT_TOTAL + ROW_COUNT;
IF(ROW_COUNT <= 0 OR PROCESS_STATUS = STATUS.ERROR) THEN
ERROR_COUNT := ERROR_COUNT + 1;
UPDATE STAGE_TBL
SET status = PROCESS_STATUS,
status_DATE = SYSDATE,
status_DESCRIPTION = STATUS_DESCRIPTION
WHERE ID = A_NewStage.ID;
ELSE
UPDATE STAGE_TBL
SET status = PROCESS_STATUS,
status_DATE = SYSDATE,
status_DESCRIPTION = STATUS_DESCRIPTION,
SHRED_DT = SYSDATE
WHERE ID = A_NewStage.ID;
END IF;
COMMIT;
END LOOP;
COMMIT;
IF ERROR_COUNT > 0 THEN
ERRMSG := '** ERROR: ' || ERROR_COUNT || ' Stage records did not insert in to the Processed table correctly';
RAISE_APPLICATION_ERROR(-20001,ErrMsg);
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END ;
My XML with just one rp_sendRow element, it can go upto 2000 rp_sendRow elements
<?xml version = \"1.0\" encoding = \"UTF-8\"?>
<rp_send xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
<rp_sendRow>
<store>0123</store>
<sales>022399190</sales>
<cost>0.01</cost>
<flag>true</flag>
<st-dt>2013-04-19</st-dt>
<st>146.51</st>
<qty>13.0</qty>
<value>0.0</value>
<start-on-order>0.0</start-on-order>
<hand>0.0</hand>
<order>0.0</order>
<commit>0.0</commit>
<sales>0.0</sales>
<rec>0.0</rec>
<val>0.0</val>
<id-1/>
<id-2/>
<id-3/>
<unit-pr>13.0</unit-pr>
<eff-dt>2015-06-16</eff-dt>
<eff-tm>09:12:21</eff-tm>
</rp_sendRow>
</rp_send>
根据 OTN 和 AskTom,问题在于 PLSQL 的版本及其在每个版本中的解析方式。
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:9522467800346460591
https://community.oracle.com/thread/3797202
解析取决于存储类型及其在 PL/SQL
的 11.2.0.4 之前的版本中效率低下
在 11.2.0.4 之前的版本中,Oracle 使用基于内存中 DOM 类 XML 文档表示的功能评估。这就是性能受到影响的原因。
我附上了一个脚本,我在其中尝试 process/parse XML in a table(STAGE_TBL) in XMLTYPE列并将解析后的数据插入另一个 table(PROCESSED_DATA_TBL)。 XML 最大可达 2MB,这会导致大约 2000 多行已解析数据。 我看到的问题是当我将 XML 对象传递给过程 (STAGE_TBL_PROCESS) 以解析它每 XML 大约需要 10 秒,而不是传递 XML如果我通过传递 ID 直接从过程 (STAGE_TBL_PROCESS) 中的 table 获取它,则大约需要 0.15 秒。 根据文档,所有 IN 参数均通过引用传递,那么为什么会出现这种性能差异?
数据库详细信息 Oracle 数据库 11g 企业版 11.2.0.3.0 版 - 64 位生产 PL/SQL 版本 11.2.0.3.0 - 生产 "CORE 11.2.0.3.0 Production" Linux 的 TNS:版本 11.2.0.3.0 - 生产 NLSRTL 版本 11.2.0.3.0 - 生产
注意:我无法执行 SQL_TRACE 或 DBMS_STATS,因为我无权访问它们。
/*
This one is taking .15 seconds to process an XML with about 2000 rp_sendRow elements
*/
DECLARE
CURSOR NewStage IS
SELECT *
FROM STAGE_TBL
WHERE status = 'N'
ORDER BY PUT_TIME ASC;
SUBTYPE rt_NewStage IS NewStage % rowtype;
ROW_COUNT INTEGER := 0; -- Return value from calling the procedure
READ_COUNT INTEGER := 0; -- Number of rows read from the stage table
INSERT_COUNT_TOTAL INTEGER := 0; -- Number of Inserts Inven records
ERROR_COUNT INTEGER := 0; -- Number of Inven inserts that did inserted more then 1 row in Inven
PROCESS_STATUS STATUS.MmsStatus;
STATUS_DESCRIPTION STATUS.MmsStatusReason;
ERRMSG VARCHAR2(500);
PROCEDURE STAGE_TBL_PROCESS (IDDATA IN RAW, PROCESS_STATUS OUT VARCHAR2, STATUS_DESCRIPTION OUT VARCHAR2, ROW_COUNT OUT NUMBER) AS
/*
This procedure is to parse the XML from STAGE_TBL and populate the data from XML to PROCESSED_DATA_TBL table
IN PARAMS
----------
IDDATA - ID from STAGE_TBL
xData - XMLType field from XML_DOCUMENT of STAGE_TBL
OUT PARAMS
-----------
PROCESS_STATUS - The STATUS of parsing and populating PROCESSED_DATA_TBL
STATUS_DESCRIPTION - The description of the STATUS of parsing and populating PROCESSED_DATA_TBL
ROW_COUNT - Number of rows inserted into PROCESSED_DATA_TBL
*/
BEGIN
INSERT ALL INTO PROCESSED_DATA_TBL
(PD_ID,
STORE,
SALES_NBR,
UNIT_COST,
ST_FLAG,
ST_DATE,
ST,
START_QTY,
START_VALUE,
START_ON_ORDER,
HAND,
ORDERED,
COMMITED,
SALES,
RECEIVE,
VALUED,
ID_1,
ID_2,
ID_3,
UNIT_PRICE,
EFFECTIVE_DATE,
STATUS,
STATUS_DATE,
STATUS_REASON)
VALUES (IDDATA
,store
,SalesNo
,UnitCost
,StWac
,StDt
,St
,StartQty
,StartValue
,StartOnOrder
,Hand
,Ordered
,COMMITED
,Sales
,Rec
,Valued
,Id1
,Id2
,Id3
,UnitPrice
,to_Date(EffectiveDate||' '||EffectiveTime, 'YYYY-MM-DD HH24:MI:SS')
,'N'
,SYSDATE
,'XML PROCESS INSERT')
WITH T AS
( SELECT STG.XML_DOCUMENT FROM STAGE_TBL STG WHERE STG.ID = IDDATA)
-- This is to parse and fetch the data from XML
SELECT E.* FROM T, XMLTABLE('rp_send/rp_sendRow' PASSING T.XML_DOCUMENT COLUMNS
store VARCHAR(20) PATH 'store'
,SalesNo VARCHAR(20) PATH 'sales'
,UnitCost NUMBER PATH 'cost'
,StWac VARCHAR(20) PATH 'flag'
,StDt DATE PATH 'st-dt'
,St NUMBER PATH 'st'
,StartQty NUMBER PATH 'qty'
,StartValue NUMBER PATH 'value'
,StartOnOrder NUMBER PATH 'start-on-order'
,Hand NUMBER PATH 'hand'
,Ordered NUMBER PATH 'order'
,Commited NUMBER PATH 'commit'
,Sales NUMBER PATH 'sales'
,Rec NUMBER PATH 'rec'
,Valued NUMBER PATH 'val'
,Id1 VARCHAR(30) PATH 'id-1'
,Id2 VARCHAR(30) PATH 'id-2'
,Id3 VARCHAR(30) PATH 'id-3'
,UnitPrice NUMBER PATH 'unit-pr'
,EffectiveDate VARCHAR(30) PATH 'eff-dt'
,EffectiveTime VARCHAR(30) PATH 'eff-tm'
) E;
ROW_COUNT := SQL%ROWCOUNT; -- Not the # of all the rows inserted.
PROCESS_STATUS := STATUS.PROCESSED;
IF ROW_COUNT < 1 THEN -- The insert failed Row Count = 0 No exception thrown
PROCESS_STATUS := STATUS.ERROR;
STATUS_DESCRIPTION := 'ERROR Did not insert into Pos Inventory. Reason Unknown';
END IF;
EXCEPTION
WHEN OTHERS THEN
ROW_COUNT := 0;
PROCESS_STATUS := STATUS.ERROR;
STATUS_DESCRIPTION := 'SqlCode:' || SQLCODE || ' SqlErrMsg:' || SQLERRM;
END;
BEGIN
DBMS_OUTPUT.enable(NULL);
FOR A_NewStage IN NewStage
LOOP
READ_COUNT := READ_COUNT + 1;
STAGE_TBL_PROCESS(A_NewStage.ID, PROCESS_STATUS, STATUS_DESCRIPTION, ROW_COUNT);
INSERT_COUNT_TOTAL := INSERT_COUNT_TOTAL + ROW_COUNT;
IF(ROW_COUNT <= 0 OR PROCESS_STATUS = STATUS.ERROR) THEN
ERROR_COUNT := ERROR_COUNT + 1;
UPDATE STAGE_TBL
SET status = PROCESS_STATUS,
status_DATE = SYSDATE,
status_DESCRIPTION = STATUS_DESCRIPTION
WHERE ID = A_NewStage.ID;
ELSE
UPDATE STAGE_TBL
SET status = PROCESS_STATUS,
status_DATE = SYSDATE,
status_DESCRIPTION = STATUS_DESCRIPTION,
SHRED_DT = SYSDATE
WHERE ID = A_NewStage.ID;
END IF;
COMMIT;
END LOOP;
COMMIT;
IF ERROR_COUNT > 0 THEN
ERRMSG := '** ERROR: ' || ERROR_COUNT || ' Stage records did not insert in to the Processed table correctly';
RAISE_APPLICATION_ERROR(-20001,ErrMsg);
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END ;
/*
This one is taking 10 seconds to process an XML with about 2000 rp_sendRow elements
*/
DECLARE
CURSOR NewStage IS
SELECT *
FROM STAGE_TBL
WHERE status = 'N'
ORDER BY PUT_TIME ASC;
SUBTYPE rt_NewStage IS NewStage % rowtype;
ROW_COUNT INTEGER := 0; -- Return value from calling the procedure
READ_COUNT INTEGER := 0; -- Number of rows read from the stage table
INSERT_COUNT_TOTAL INTEGER := 0; -- Number of Inserts Inven records
ERROR_COUNT INTEGER := 0; -- Number of Inven inserts that did inserted more then 1 row in Inven
PROCESS_STATUS STATUS.MmsStatus;
STATUS_DESCRIPTION STATUS.MmsStatusReason;
ERRMSG VARCHAR2(500);
PROCEDURE STAGE_TBL_PROCESS (IDDATA IN RAW, xData IN STAGE_TBL.XML_DOCUMENT%TYPE, PROCESS_STATUS OUT VARCHAR2, STATUS_DESCRIPTION OUT VARCHAR2, ROW_COUNT OUT NUMBER) AS
/*
This procedure is to parse the XML from STAGE_TBL and populate the data from XML to PROCESSED_DATA_TBL table
IN PARAMS
----------
IDDATA - ID from STAGE_TBL
xData - XMLType field from XML_DOCUMENT of STAGE_TBL
OUT PARAMS
-----------
PROCESS_STATUS - The STATUS of parsing and populating PROCESSED_DATA_TBL
STATUS_DESCRIPTION - The description of the STATUS of parsing and populating PROCESSED_DATA_TBL
ROW_COUNT - Number of rows inserted into PROCESSED_DATA_TBL
*/
BEGIN
INSERT ALL INTO PROCESSED_DATA_TBL
(PD_ID,
STORE,
SALES_NBR,
UNIT_COST,
ST_FLAG,
ST_DATE,
ST,
START_QTY,
START_VALUE,
START_ON_ORDER,
HAND,
ORDERED,
COMMITED,
SALES,
RECEIVE,
VALUED,
ID_1,
ID_2,
ID_3,
UNIT_PRICE,
EFFECTIVE_DATE,
STATUS,
STATUS_DATE,
STATUS_REASON)
VALUES (IDDATA
,store
,SalesNo
,UnitCost
,StWac
,StDt
,St
,StartQty
,StartValue
,StartOnOrder
,Hand
,Ordered
,COMMITED
,Sales
,Rec
,Valued
,Id1
,Id2
,Id3
,UnitPrice
,to_Date(EffectiveDate||' '||EffectiveTime, 'YYYY-MM-DD HH24:MI:SS')
,'N'
,SYSDATE
,'XML PROCESS INSERT')
-- This is to parse and fetch the data from XML
SELECT E.* FROM XMLTABLE('rp_send/rp_sendRow' PASSING xDATA COLUMNS
store VARCHAR(20) PATH 'store'
,SalesNo VARCHAR(20) PATH 'sales'
,UnitCost NUMBER PATH 'cost'
,StWac VARCHAR(20) PATH 'flag'
,StDt DATE PATH 'st-dt'
,St NUMBER PATH 'st'
,StartQty NUMBER PATH 'qty'
,StartValue NUMBER PATH 'value'
,StartOnOrder NUMBER PATH 'start-on-order'
,Hand NUMBER PATH 'hand'
,Ordered NUMBER PATH 'order'
,Commited NUMBER PATH 'commit'
,Sales NUMBER PATH 'sales'
,Rec NUMBER PATH 'rec'
,Valued NUMBER PATH 'val'
,Id1 VARCHAR(30) PATH 'id-1'
,Id2 VARCHAR(30) PATH 'id-2'
,Id3 VARCHAR(30) PATH 'id-3'
,UnitPrice NUMBER PATH 'unit-pr'
,EffectiveDate VARCHAR(30) PATH 'eff-dt'
,EffectiveTime VARCHAR(30) PATH 'eff-tm'
) E;
ROW_COUNT := SQL%ROWCOUNT; -- Not the # of all the rows inserted.
PROCESS_STATUS := STATUS.PROCESSED;
IF ROW_COUNT < 1 THEN -- The insert failed Row Count = 0 No exception thrown
PROCESS_STATUS := STATUS.ERROR;
STATUS_DESCRIPTION := 'ERROR Did not insert into Pos Inventory. Reason Unknown';
END IF;
EXCEPTION
WHEN OTHERS THEN
ROW_COUNT := 0;
PROCESS_STATUS := STATUS.ERROR;
STATUS_DESCRIPTION := 'SqlCode:' || SQLCODE || ' SqlErrMsg:' || SQLERRM;
END;
BEGIN
DBMS_OUTPUT.enable(NULL);
FOR A_NewStage IN NewStage
LOOP
READ_COUNT := READ_COUNT + 1;
STAGE_TBL_PROCESS(A_NewStage.ID, A_NewStage.XML_DOCUMENT, PROCESS_STATUS, STATUS_DESCRIPTION, ROW_COUNT);
INSERT_COUNT_TOTAL := INSERT_COUNT_TOTAL + ROW_COUNT;
IF(ROW_COUNT <= 0 OR PROCESS_STATUS = STATUS.ERROR) THEN
ERROR_COUNT := ERROR_COUNT + 1;
UPDATE STAGE_TBL
SET status = PROCESS_STATUS,
status_DATE = SYSDATE,
status_DESCRIPTION = STATUS_DESCRIPTION
WHERE ID = A_NewStage.ID;
ELSE
UPDATE STAGE_TBL
SET status = PROCESS_STATUS,
status_DATE = SYSDATE,
status_DESCRIPTION = STATUS_DESCRIPTION,
SHRED_DT = SYSDATE
WHERE ID = A_NewStage.ID;
END IF;
COMMIT;
END LOOP;
COMMIT;
IF ERROR_COUNT > 0 THEN
ERRMSG := '** ERROR: ' || ERROR_COUNT || ' Stage records did not insert in to the Processed table correctly';
RAISE_APPLICATION_ERROR(-20001,ErrMsg);
END IF;
EXCEPTION
WHEN OTHERS THEN
RAISE;
END ;
My XML with just one rp_sendRow element, it can go upto 2000 rp_sendRow elements
<?xml version = \"1.0\" encoding = \"UTF-8\"?>
<rp_send xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">
<rp_sendRow>
<store>0123</store>
<sales>022399190</sales>
<cost>0.01</cost>
<flag>true</flag>
<st-dt>2013-04-19</st-dt>
<st>146.51</st>
<qty>13.0</qty>
<value>0.0</value>
<start-on-order>0.0</start-on-order>
<hand>0.0</hand>
<order>0.0</order>
<commit>0.0</commit>
<sales>0.0</sales>
<rec>0.0</rec>
<val>0.0</val>
<id-1/>
<id-2/>
<id-3/>
<unit-pr>13.0</unit-pr>
<eff-dt>2015-06-16</eff-dt>
<eff-tm>09:12:21</eff-tm>
</rp_sendRow>
</rp_send>
根据 OTN 和 AskTom,问题在于 PLSQL 的版本及其在每个版本中的解析方式。
https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:9522467800346460591 https://community.oracle.com/thread/3797202
解析取决于存储类型及其在 PL/SQL
的 11.2.0.4 之前的版本中效率低下在 11.2.0.4 之前的版本中,Oracle 使用基于内存中 DOM 类 XML 文档表示的功能评估。这就是性能受到影响的原因。