如何在Oracle PLSQL中使用dbms_xmldom以获得良好的函数性能?
How to use dbms_xmldom in Oracle PLSQL in order to get a good function performance?
我正在使用 Oracle 版本 12 第 1 版
我一直在尝试编写一个函数来计算存储为 XML 的对象之间的某种距离。
为此,我做了以下...
首先,注册 XML 架构。
BEGIN
-- Register the schema
DBMS_XMLSCHEMA.registerSchema('http://www.example.com/fvInteger.xsd',
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="FeatureVector">
<xs:complexType>
<xs:sequence>
<xs:element name="feature" type="xs:integer" minOccurs="5" maxOccurs="999"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>',
TRUE, TRUE, FALSE);
END;
/
然后创建 table
CREATE TABLE cophirfvXML_int (
id NUMBER,
complex_obj XMLTYPE)
XMLTYPE complex_obj STORE AS OBJECT RELATIONAL
XMLSCHEMA "http://www.example.com/fvInteger.xsd"
ELEMENT "FeatureVector";
将以下数据插入到上面table
ID=1
<FeatureVector><feature>85</feature><feature>-41</feature><feature>29</feature><feature>26</feature><feature>-29</feature><feature>1</feature><feature>-29</feature><feature>-8</feature><feature>15</feature><feature>6</feature><feature>-17</feature><feature>6</feature><feature>-27</feature><feature>8</feature><feature>-12</feature><feature>5</feature></FeatureVector>
ID=2
<FeatureVector><feature>98</feature><feature>77</feature><feature>-127</feature><feature>27</feature><feature>-30</feature><feature>-13</feature><feature>-1</feature><feature>14</feature><feature>-31</feature><feature>-56</feature><feature>-10</feature><feature>6</feature><feature>-10</feature><feature>-12</feature><feature>5</feature><feature>19</feature></
FeatureVector>
... and so on (I am working with 200.000 objects).
最后,函数>>
create or replace FUNCTION myDistance(
innXML XMLType,
outXML XMLType
) RETURN number
IS
total NUMBER := 0;
docInn xmldom.DOMDocument;
docOut xmldom.DOMDocument;
nInn xmldom.DOMNode;
nOut xmldom.DOMNode;
nlInn xmldom.DOMNodeList;
nlOut xmldom.DOMNodeList;
len number;
BEGIN
--Converte os atributos xmltype para DOMDocuments.
docInn := dbms_xmldom.newDOMDocument(innXML);
docOut := dbms_xmldom.newDOMDocument(outXML);
nlInn := xmldom.getElementsByTagName(docInn, '*');
nlOut := xmldom.getElementsByTagName(docOut, '*');
len := xmldom.getLength(nlInn);
for i in 1..len-1 loop
nInn := xmldom.item(nlInn, i);
nOut := xmldom.item(nlOut, i);
total := total + ABS(xmldom.getNodeValue(DBMS_XMLDOM.getFirstChild(nInn)) - xmldom.getNodeValue(DBMS_XMLDOM.getFirstChild(nOut)));
end loop;
RETURN total;
END;
/
函数性能很差。它使用了过多的内存并且比预期的要慢得多(主要是由于使用了对象关系存储)。
我什至得到错误:
ORA-00039: erro durante ac?o periodica ORA-04036: Memoria PGA usada
pela instancia excede PGA_AGGREGATE_LIMIT ORA-06512: em
"XDB.DBMS_XMLDOM", line 5027 ORA-06512: em "XDB.DBMS_XMLDOM", line
5052 ORA-06512: em "HIGIIA.XML_MANHATTAN_DISTANCE", line 19
此外,我使用查询尝试了下面这个不同的解决方案,但性能也不是很好。
SELECT SUM( ABS(oFV.feature - iFV.feature) )
INTO total
FROM XMLTABLE(
'//FeatureVector/feature'
PASSING outXML
COLUMNS rn FOR ORDINALITY,
feature NUMBER PATH '.'
) oFV
INNER JOIN
XMLTABLE(
'//FeatureVector/feature'
PASSING innXML
COLUMNS rn FOR ORDINALITY,
feature NUMBER PATH '.'
) ifv
ON ( oFV.rn = iFV.rn );
我可以做些什么来提高它的性能?
I do need to improve the performance, not solve the ORA-00039 error
increasing the PGA Aggregate Limit.
希望有人能帮忙!提前致谢!!
一些事情 - 我猜你的内存不足是由于没有调用 DBMS_XMLDOM.freeDocument(docXXX);
但至于性能问题 - 没有及时的具体信息,很难说代码是否存在问题,或者这是否是与解析相关 xmltype 字段值相关的预期开销。我的直接印象是,预先计算并存储 "distance" 值(当 xml 为 inserted/updated/deleted 时)。这样你就可以直接通过 sql 查询数据,而不需要读取端的所有解析开销。如果您想保持 xml 模式干净,您可以将计算值存储在 xml 或关系 table 中。
我正在使用 Oracle 版本 12 第 1 版
我一直在尝试编写一个函数来计算存储为 XML 的对象之间的某种距离。
为此,我做了以下...
首先,注册 XML 架构。
BEGIN
-- Register the schema
DBMS_XMLSCHEMA.registerSchema('http://www.example.com/fvInteger.xsd',
'<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="FeatureVector">
<xs:complexType>
<xs:sequence>
<xs:element name="feature" type="xs:integer" minOccurs="5" maxOccurs="999"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>',
TRUE, TRUE, FALSE);
END;
/
然后创建 table
CREATE TABLE cophirfvXML_int (
id NUMBER,
complex_obj XMLTYPE)
XMLTYPE complex_obj STORE AS OBJECT RELATIONAL
XMLSCHEMA "http://www.example.com/fvInteger.xsd"
ELEMENT "FeatureVector";
将以下数据插入到上面table
ID=1
<FeatureVector><feature>85</feature><feature>-41</feature><feature>29</feature><feature>26</feature><feature>-29</feature><feature>1</feature><feature>-29</feature><feature>-8</feature><feature>15</feature><feature>6</feature><feature>-17</feature><feature>6</feature><feature>-27</feature><feature>8</feature><feature>-12</feature><feature>5</feature></FeatureVector>
ID=2
<FeatureVector><feature>98</feature><feature>77</feature><feature>-127</feature><feature>27</feature><feature>-30</feature><feature>-13</feature><feature>-1</feature><feature>14</feature><feature>-31</feature><feature>-56</feature><feature>-10</feature><feature>6</feature><feature>-10</feature><feature>-12</feature><feature>5</feature><feature>19</feature></
FeatureVector>
... and so on (I am working with 200.000 objects).
最后,函数>>
create or replace FUNCTION myDistance(
innXML XMLType,
outXML XMLType
) RETURN number
IS
total NUMBER := 0;
docInn xmldom.DOMDocument;
docOut xmldom.DOMDocument;
nInn xmldom.DOMNode;
nOut xmldom.DOMNode;
nlInn xmldom.DOMNodeList;
nlOut xmldom.DOMNodeList;
len number;
BEGIN
--Converte os atributos xmltype para DOMDocuments.
docInn := dbms_xmldom.newDOMDocument(innXML);
docOut := dbms_xmldom.newDOMDocument(outXML);
nlInn := xmldom.getElementsByTagName(docInn, '*');
nlOut := xmldom.getElementsByTagName(docOut, '*');
len := xmldom.getLength(nlInn);
for i in 1..len-1 loop
nInn := xmldom.item(nlInn, i);
nOut := xmldom.item(nlOut, i);
total := total + ABS(xmldom.getNodeValue(DBMS_XMLDOM.getFirstChild(nInn)) - xmldom.getNodeValue(DBMS_XMLDOM.getFirstChild(nOut)));
end loop;
RETURN total;
END;
/
函数性能很差。它使用了过多的内存并且比预期的要慢得多(主要是由于使用了对象关系存储)。
我什至得到错误:
ORA-00039: erro durante ac?o periodica ORA-04036: Memoria PGA usada pela instancia excede PGA_AGGREGATE_LIMIT ORA-06512: em "XDB.DBMS_XMLDOM", line 5027 ORA-06512: em "XDB.DBMS_XMLDOM", line 5052 ORA-06512: em "HIGIIA.XML_MANHATTAN_DISTANCE", line 19
此外,我使用查询尝试了下面这个不同的解决方案,但性能也不是很好。
SELECT SUM( ABS(oFV.feature - iFV.feature) )
INTO total
FROM XMLTABLE(
'//FeatureVector/feature'
PASSING outXML
COLUMNS rn FOR ORDINALITY,
feature NUMBER PATH '.'
) oFV
INNER JOIN
XMLTABLE(
'//FeatureVector/feature'
PASSING innXML
COLUMNS rn FOR ORDINALITY,
feature NUMBER PATH '.'
) ifv
ON ( oFV.rn = iFV.rn );
我可以做些什么来提高它的性能?
I do need to improve the performance, not solve the ORA-00039 error increasing the PGA Aggregate Limit.
希望有人能帮忙!提前致谢!!
一些事情 - 我猜你的内存不足是由于没有调用 DBMS_XMLDOM.freeDocument(docXXX);
但至于性能问题 - 没有及时的具体信息,很难说代码是否存在问题,或者这是否是与解析相关 xmltype 字段值相关的预期开销。我的直接印象是,预先计算并存储 "distance" 值(当 xml 为 inserted/updated/deleted 时)。这样你就可以直接通过 sql 查询数据,而不需要读取端的所有解析开销。如果您想保持 xml 模式干净,您可以将计算值存储在 xml 或关系 table 中。