That was fine for my situation, but what if you need something faster? As I previously said
One option is to register a schema in the database, create a table based off that schema, store the XML in there and parse it that way (if still needed).
To verify the answer, I took the long way to get to the above just to see what happens. I started by creating a simple schema for the XML, doing a basic schema registration, converting the XML to a schema based XML and parsing that PL/SQL XMLType. The basics of that approach were
DECLARE
l_schema CLOB;
BEGIN
l_schema := '<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xdb="http://xmlns.oracle.com/xdb">
<xs:element name="resultset" type="resultSetType" xdb:defaultTable="LOAD_TEMP_RESULT"/>
<xs:complexType name="resultSetType">
<xs:sequence>
<xs:element name="row" type="rowType" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="rowType">
<xs:sequence>
...16 elements of xs:int, xs:string, xs:short, xs:date ...
</xs:sequence>
</xs:complexType>
</xs:schema>';
dbms_xmlSchema.registerSchema('blog_pref.xsd', l_schema, gentypes => false, gentables => false);
END;/
declare
l_result_xml XMLTYPE;
l_ns_xml XMLTYPE;
l_start NUMBER;
l_end NUMBER;
begin
-- Build up the XML
-- Has 2100+ row nodes
...snipped...
l_start := dbms_utility.get_time;
l_ns_xml := l_result_xml.createSchemaBasedXML('blog_pref.xsd');
INSERT INTO import_queue
(...20 columns...)
SELECT CBIQ_ID_SEQ, CBRH_ID_SEQ,
...18 columns ...
FROM XMLTABLE('/resultset/row'
PASSING l_ns_xml
COLUMNS
CBIQ_ID_SEQ NUMBER(11) PATH 'CBIQ_ID_SEQ',
CBRH_ID_SEQ NUMBER(11) PATH 'CBRH_ID_SEQ',
... 18 more columns ...);
l_end := dbms_utility.get_time;
dbms_output.put_line('INSERT INTO TIME in sec: ' || to_char((l_end - l_start) / 100));
rollback;
end;INSERT INTO TIME in sec: 1024.09
This was still 16+ minutes so no improvement at all. I wasn't expecting any improvement in overall time because
A) The schema had been registered without creating any types or tables
B) The code is still parsing a PL/SQL XMLType variable.
The only difference now is that the XML is associated to a schema but the object itself is still simply a PL/SQL XMLType variable. The next approach was to use the default schema registration. The only change to the above was to use
dbms_xmlSchema.registerSchema('blog_pref.xsd', l_schema);INSERT INTO TIME in sec: 1057.13
This was still 16+ minutes so no improvement at all. I wasn't expecting any improvement in overall time because I had only removed condition A) from above above and condition B) was still in effect.
To remove condition B), I rewrote the code to insert into the table created during the registerSchema process and then read from that table using XMLTable to parse the XML. I used xdb:defaultTable="LOAD_TEMP_RESULT" in the schema to name the table that Oracle created. The code ended up looking like
declare
l_result_xml XMLTYPE;
l_ns_xml XMLTYPE;
l_start NUMBER;
l_end NUMBER;
begin
-- Build up the XML
-- Has 2100+ row nodes
...snipped...
l_start := dbms_utility.get_time;
INSERT INTO LOAD_TEMP_RESULT VALUES l_result_xml;
l_end := dbms_utility.get_time;
dbms_output.put_line('INSERT INTO TEMP TIME in sec: ' || to_char((l_end - l_start) / 100));
l_start := dbms_utility.get_time;
INSERT INTO import_queue
(...20 columns...)
SELECT CBIQ_ID_SEQ, CBRH_ID_SEQ,
...18 columns ...
FROM LOAD_TEMP_RESULT ltr,
XMLTABLE('/resultset/row'
PASSING ltr.object_value -- column alias name
COLUMNS
CBIQ_ID_SEQ NUMBER(11) PATH 'CBIQ_ID_SEQ',
CBRH_ID_SEQ NUMBER(11) PATH 'CBRH_ID_SEQ',
... 18 more columns ...);
l_end := dbms_utility.get_time;
dbms_output.put_line('INSERT INTO TIME in sec: ' || to_char((l_end - l_start) / 100));
rollback;
end;INSERT INTO TEMP TIME in sec: .31
INSERT INTO TIME in sec: .17
So the time Oracle spent parsing the XML into the temporary table and then retrieving the data from that and inserting it into the import_queue table was less than 0.5 seconds for 2100 rows. That was a very good improvement over 4 seconds, though it does require the registration of a schema and a table assocaited to that schema.
Still to be covered was the other option I mentioned of
store the XML as binary XML (available in 11g). Hopefully I get to that soon.
No comments:
Post a Comment