我试图编写一个优化的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小时+)
答案 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;