Hi,
I need to append some XML to a vary large XML doc (6.7mb), and it's taking a really long time. For one or two records, it wouldn't be a problem, but I have to do this on hundreds of thousands of records.
Here are the three different ways I've tried so far:
dbms_xmldom:
~5.5 secs.
Clob Concatenation:
~7.1 secs.
Java Stringbuffer Concatenation:
Note: This is not perfect and was just a POC.
~6.6 secs.
None of these are fast, but if I could shave even half a second off, it would make a huge difference. Does anyone have an idea for a faster way to append xml to a really large XML Doc?
Thanks,
Mike
I need to append some XML to a vary large XML doc (6.7mb), and it's taking a really long time. For one or two records, it wouldn't be a problem, but I have to do this on hundreds of thousands of records.
Here are the three different ways I've tried so far:
dbms_xmldom:
Code:
FUNCTION insert_node(p_xml1 XMLTYPE, p_xml2 XMLTYPE) RETURN XMLTYPE AS
v_doc1 dbms_xmldom.domdocument;
v_doc2 dbms_xmldom.domdocument;
v_node1 dbms_xmldom.domnode;
v_node2 dbms_xmldom.domnode;
BEGIN
v_doc1 := dbms_xmldom.newdomdocument(p_xml1);
v_doc2 := dbms_xmldom.newdomdocument(p_xml2);
v_node1 := dbms_xmldom.makenode(dbms_xmldom.getdocumentelement(v_doc1));
v_node2 := dbms_xmldom.makenode(dbms_xmldom.getdocumentelement(v_doc2));
v_node2 := dbms_xmldom.importnode(v_doc1, v_node2, true);
v_node1 := dbms_xmldom.appendchild(v_node1, v_node2);
RETURN dbms_xmldom.getxmltype(v_doc1);
END insert_node;
Clob Concatenation:
Code:
FUNCTION insert_node(p_xml1 XMLTYPE, p_xml2 XMLTYPE) RETURN XMLTYPE AS
v_clob1 CLOB := p_xml1.getClobVal();
v_clob2 CLOB := p_xml2.extract('/*').getClobVal();
v_dest CLOB := EMPTY_CLOB;
v_close VARCHAR2(100) := '</'||p_xml1.getRootElement()||'>';
v_len1 NUMBER;
v_len2 NUMBER;
v_close_idx NUMBER;
BEGIN
dbms_lob.createtemporary(v_dest, TRUE);
v_len1 := dbms_lob.getlength(v_clob1);
v_len2 := dbms_lob.getlength(v_clob2);
v_close_idx := v_len1 - LENGTH(v_close);
dbms_lob.copy(v_dest, v_clob1, v_close_idx, 1, 1);
dbms_lob.writeappend(v_dest, v_len2, v_clob2);
dbms_lob.writeappend(v_dest, LENGTH(v_close), v_close);
RETURN XMLTYPE(v_dest);
END insert_node;
Java Stringbuffer Concatenation:
Note: This is not perfect and was just a POC.
Code:
CREATE OR REPLACE AND COMPILE JAVA SOURCE NAMED StringUtils AS
import oracle.sql.CLOB;
import java.io.Reader;
import java.io.Writer;
import java.io.PrintWriter;
import java.lang.Exception;
public class StringUtils {
public static void concat(oracle.sql.CLOB clob1, oracle.sql.CLOB clob2, oracle.sql.CLOB output) throws Exception
{
try
{
Writer w = output.getCharacterOutputStream();
PrintWriter pw = new PrintWriter(w);
StringBuffer sb = new StringBuffer();
Reader clobStream;
int nchars = 0;
char[] buffer = new char[100000];
clobStream = clob1.getCharacterStream();
while((nchars = clobStream.read(buffer)) != -1)
sb.append(buffer, 0, nchars);
clobStream.close();
clobStream = clob2.getCharacterStream();
while((nchars = clobStream.read(buffer)) != -1)
sb.append(buffer, 0, nchars);
clobStream.close();
pw.write(sb.toString().toCharArray());
pw.close();
}
catch (Exception ex)
{
throw ex;
}
}
}
CREATE OR REPLACE PROCEDURE java_concat(p_clob1 CLOB, p_clob2 CLOB, output CLOB) IS
LANGUAGE JAVA NAME 'StringUtils.concat(oracle.sql.CLOB, oracle.sql.CLOB, oracle.sql.CLOB)';
None of these are fast, but if I could shave even half a second off, it would make a huge difference. Does anyone have an idea for a faster way to append xml to a really large XML Doc?
Thanks,
Mike