【问题标题】:Parsing Large XML (>4k) in PL/SQL在 PL/SQL 中解析大型 XML (>4k)
【发布时间】:2011-11-08 19:22:50
【问题描述】:

我得到一个长度约为 30k 的 xml。我必须从这个 xml 中提取键和值对并插入到表中。还必须避免表中的重复行。这是我想出的查询:

DECLARE
  PARSER XMLPARSER.PARSER;
  XMLDOC XMLDOM.DOMDOCUMENT;
  NODELIST XMLDOM.DOMNODELIST;
  REFDATA VARCHAR2(32767);
  REFDATAPART VARCHAR2(32767);
  NODELENGTH NUMBER;

开始

  REFDATA := '<ReferenceFields><ReferenceField><FieldKey>Name1</FieldKey>                  <FieldValue>ABCD</FieldValue></ReferenceField><ReferenceField><FieldKey>Name1</FieldKey><FieldValue>ABCD</FieldValue></ReferenceField></ReferenceFields>';
  PARSER := XMLPARSER.NEWPARSER;
  XMLPARSER.PARSEBUFFER(PARSER,REFDATA);
  XMLDOC := XMLPARSER.GETDOCUMENT(PARSER);
  NODELIST := XMLDOM.GETELEMENTSBYTAGNAME(XMLDOC, 'ReferenceField');
  NODELENGTH := XMLDOM.GETLENGTH(NODELIST);
  FOR i IN 0..NODELENGTH-1 LOOP

    XMLDOM.WRITETOBUFFER(XMLDOM.ITEM(NODELIST, i),REFDATAPART);
    INSERT INTO 
        HTS_TRANSACTION_XREF(TRANS_ID,XREF_FIELD, XREF_VALUE) 
    SELECT 
        '1',
        EXTRACTVALUE(COLUMN_VALUE, '/ReferenceField/FieldKey') "FIELDKEY",
        EXTRACTVALUE(COLUMN_VALUE, '/ReferenceField/FieldValue') "FIELDVALUE"
    FROM 
        TABLE(XMLSequence(XMLTYPE(REFDATAPART))) REFDATA
    WHERE 
        NOT EXISTS (SELECT 1 from TRANSACTION_CROSSREFERENCE WHERE TRANS_ID='1' AND XREF_FIELD=EXTRACTVALUE(column_value, '/ReferenceField/FieldKey') AND XREF_VALUE=EXTRACTVALUE(column_value, '/ReferenceField/FieldValue'));

  END LOOP;

XMLPARSER.FREEPARSER(PARSER);

结束;

此查询运行良好,最终将成为 sproc 的一部分。

这里我有两个问题:

1- 这是处理最大大小为 32k 的大型 xml 的正确方法吗?

2- 这是否足以在一秒钟内处理 700 个呼叫?

谢谢, 态度

【问题讨论】:

  • "2- 这是否足够高效以在一秒钟内处理 700 个呼叫?" - 这是在什么硬件上运行,还有什么其他的东西在上面运行,等等。这是一个只有你能回答的问题。就个人而言,我不会在数据库中进行这种处理,而是在应用程序服务器中进行,您可以更好(并且更便宜)扩展以满足您的要求。
  • 您还可以查看 XMLTYPE,在我看来,它比 XMLPARSER 更易于使用。不知道它是否会表现得更好。 32K 应该不会造成问题,但是我在 XMLTYPE 中看到了使用大小为 MB 的 XML 的性能问题。对于 700 tps,我会考虑使用中间层应用服务器来完成繁重的 XML 提升并比较两种方法的性能。

标签: xml oracle xmltype


【解决方案1】:

我认为您肯定希望至少收集插页。我不知道 NODELENGTH 有多大,但您可以使用类似于:

在你的声明部分:

TYPE T_STRING IS TABLE OF VARCHAR2(1024); -- adjust size
arr T_STRING    := T_STRING();

在 pl 正文中:

REFDATA         := '<ReferenceFields><ReferenceField><FieldKey>Name1</FieldKey>                  <FieldValue>ABCD</FieldValue></ReferenceField><ReferenceField><FieldKey>Name1</FieldKey><FieldValue>ABCD</FieldValue></ReferenceField></ReferenceFields>';
PARSER          := XMLPARSER.NEWPARSER;
XMLPARSER.PARSEBUFFER(PARSER,REFDATA);
XMLDOC          := XMLPARSER.GETDOCUMENT(PARSER);
NODELIST        := XMLDOM.GETELEMENTSBYTAGNAME(XMLDOC, 'ReferenceField');
NODELENGTH      := XMLDOM.GETLENGTH(NODELIST);


FOR i IN 0..NODELENGTH-1 LOOP
    XMLDOM.WRITETOBUFFER(XMLDOM.ITEM(NODELIST, i), REFDATAPART);
    arr.EXTEND();
    arr(arr.COUNT) := XMLSequence(XMLTYPE(REFDATAPART));
END LOOP;

FORALL i IN arr.FIRST..arr.LAST
    INSERT INTO HTS_TRANSACTION_XREF(TRANS_ID,XREF_FIELD, XREF_VALUE)       
        SELECT 
            '1',
            EXTRACTVALUE(arr(i), '/ReferenceField/FieldKey') "FIELDKEY",
            EXTRACTVALUE(arr(i), '/ReferenceField/FieldValue') "FIELDVALUE"
        FROM 
            dual
        WHERE 
            NOT EXISTS (
                SELECT 1 FROM TRANSACTION_CROSSREFERENCE 
                WHERE 
                    TRANS_ID   = '1' 
                AND XREF_FIELD = EXTRACTVALUE(arr(i), '/ReferenceField/FieldKey') 
                AND XREF_VALUE = EXTRACTVALUE(arr(i), '/ReferenceField/FieldValue')
            );


XMLPARSER.FREEPARSER(PARSER);

我也不知道不存在部分的目的是什么,你确定这是必要的吗?

【讨论】:

    猜你喜欢
    • 2013-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-14
    相关资源
    最近更新 更多