Oracle SQL - 计算clob类型列中的XML节点

时间:2017-11-16 14:52:51

标签: sql xml oracle count clob

我试图编写一个优化的SQL查询来计算clob类型列中的特定XML节点,现在我使用REGEXP_COUNT来浏览所有行和所有XML,但这非常慢。

像这样:

SELECT sum(REGEXP_COUNT(clobtype_column_withXMLs, '/Node_Closing_tag', 1)) as 'Node_number' FROM MY_TABLE;

这样做有效,但是数以亿计的标签需要很长时间。

我想绕过XML结构并缩短计数时间。我找到了一些东西,但大多数都涉及将列类型更改为xml并使用xquery和其他DML函数。
在我的情况下,我无法修改表,我只需要数字,指定节点在列中出现的次数。

我的表结构:

不是XML表,各种列类型和CLOB type column,其中每行包含不同大小的XML(数亿个字符)。 XML具有相当复杂的结构,我搜索的一个节点位于中间:

1/2/3/4/5/I'm_searching_for_this/contains_multiple_nodes

有没有快速的方法来计算这样的结构中的节点,而不修改表中的任何内容?我的意思是快速,在最多几个小时内计算5亿个节点。 (文本搜索需要24小时+)

2 个答案:

答案 0 :(得分:1)

替换和测量长度差异技巧shoudl为您工作的结果与REGEXP_COUNT相同(当您解析XML时,不需要相同的精度并计算元素,这应该具有最终的精确度。)

REPLACE方法的优势在于它将是最快的实施方式。

简单

  • 使用NULL

  • 替换原始字符串中搜索到的子字符串的每个出现次数
  • 计算原始字符串和替换字符串

  • 的长度差异
  • 将结果除以子字符串的长度以获得结果计数

select 
 sum(REGEXP_COUNT(clobtype_column_withXMLs, '/Node_Closing_tag', 1)) cnt1,
 sum( (length(clobtype_column_withXMLs) - length(replace(clobtype_column_withXMLs,'/Node_Closing_tag',null)))  / length('/Node_Closing_tag')) cnt2
from tst

我建议使用不同的搜索子字符串执行一些测试

 /tag
 tag/
 <tag>
 </tag>
 <tag/>

并比较结果,看看这个方法是否可靠。

答案 1 :(得分:0)

您不必更改表中的列类型即可使用XML查询,您可以使用XMLQuery或XMLTable动态转换。

一种选择是使用XMLTable提取所有相关节点,并计算您获得的数量:

select count(*)
from your_table
cross join xmltable(
  '//targetNodeName'
  passing xmltype(clobtype_column_withXMLs)
  columns dummy varchar2(1) path '@dummy'
);

XMLTable为每个匹配节点生成一行。由于你只计算它们,而不使用该节点的内容,我使用了一个虚拟列名和内容,选择了一个可能不存在的属性名称 - 如果可能的话,将其更改为其他名称。因此,dummy值将为null,但无论如何count(*)都将计算它们。

如何执行必须进行测试...它可能比使用正则表达式更糟糕。它允许您搜索自闭标签,这可能对您根据您当前正在做的事情无关紧要。

如果有用,您还可以对此进行调整,以计算原始表中每个CLOB / XML值中的节点数;如果它有一个ID列,例如:

select t.id, count(*)
from your_table t
cross join xmltable(
  '//targetNodeName'
  passing xmltype(clobtype_column_withXMLs)
  columns dummy varchar2(1) path '@dummy'
)
group by t.id;