Oracle SQL - 在 clob 类型列中计算 XML 个节点
Oracle SQL - Count XML nodes in a clob type column
我试图编写一个优化的 SQL 查询来计算 clob 类型列中的特定 XML 节点,现在我正在使用 REGEXP_COUNT 浏览所有行和所有 XMLs,但这非常慢。
像这样:
SELECT sum(REGEXP_COUNT(clobtype_column_withXMLs, '/Node_Closing_tag', 1)) as 'Node_number' FROM MY_TABLE;
这行得通,但是有数亿个标签,这确实需要很长时间。
我想绕过XML结构,缩短计数时间。我发现了一些东西,但其中大部分涉及将列类型更改为 xml 并使用 xquery 和其他 DML 函数。
在我的例子中,我无法修改 table,我只需要数字,即指定节点在列中出现的次数。
我的table结构:
不是 XML Table,各种列类型和 CLOB type column
,其中每一行包含不同大小的 XML(数亿个字符)。
XML 结构比较复杂,我要找的节点在中间:
1/2/3/4/5/I'm_searching_for_this/contains_multiple_nodes
有没有什么快速的方法可以在不修改 table 中的任何内容的情况下对这样的结构中的节点进行计数?快速我的意思是,最多在几个小时内计算 5 亿个节点。 (文本搜索需要 24 小时以上)
替换和测量长度差异 技巧应该为您工作,结果与 REGEXP_COUNT
相同(当您 解析XML并统计元素,应该是最终精度)。
REPLACE
方法的优点是它的实施速度最快。
简单
用NULL
替换原始字符串中每个出现的搜索子串
计算原串与替换串的长度差
结果除以子串长度得到结果count
.
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/>
并比较结果,看看这个方法是否可靠。
您不必更改 table 中的列类型即可使用 XML 查询,您可以使用 XMLQuery 或 XML表.
一种选择是使用XML表提取所有相关节点,并计算返回的节点数:
select count(*)
from your_table
cross join xmltable(
'//targetNodeName'
passing xmltype(clobtype_column_withXMLs)
columns dummy varchar2(1) path '@dummy'
);
XML表为每个匹配节点生成一行。由于您只对它们进行计数,而不使用该节点的内容,因此我使用了虚拟列名称和内容,选择了一个可能不存在的属性名称——如果可能,将其更改为其他名称。 dummy
值因此将为空,但 count(*)
无论如何都会计算它们。
当然必须测试它的性能如何……它可能比使用正则表达式更糟糕。不过,它会允许您搜索自闭标签,根据您当前正在做的事情,这对您来说可能无关紧要。
如果有用的话,您还可以调整它以计算原始 table 中每个 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;
我试图编写一个优化的 SQL 查询来计算 clob 类型列中的特定 XML 节点,现在我正在使用 REGEXP_COUNT 浏览所有行和所有 XMLs,但这非常慢。
像这样:
SELECT sum(REGEXP_COUNT(clobtype_column_withXMLs, '/Node_Closing_tag', 1)) as 'Node_number' FROM MY_TABLE;
这行得通,但是有数亿个标签,这确实需要很长时间。
我想绕过XML结构,缩短计数时间。我发现了一些东西,但其中大部分涉及将列类型更改为 xml 并使用 xquery 和其他 DML 函数。
在我的例子中,我无法修改 table,我只需要数字,即指定节点在列中出现的次数。
我的table结构:
不是 XML Table,各种列类型和 CLOB type column
,其中每一行包含不同大小的 XML(数亿个字符)。
XML 结构比较复杂,我要找的节点在中间:
1/2/3/4/5/I'm_searching_for_this/contains_multiple_nodes
有没有什么快速的方法可以在不修改 table 中的任何内容的情况下对这样的结构中的节点进行计数?快速我的意思是,最多在几个小时内计算 5 亿个节点。 (文本搜索需要 24 小时以上)
替换和测量长度差异 技巧应该为您工作,结果与 REGEXP_COUNT
相同(当您 解析XML并统计元素,应该是最终精度)。
REPLACE
方法的优点是它的实施速度最快。
简单
用
NULL
替换原始字符串中每个出现的搜索子串
计算原串与替换串的长度差
结果除以子串长度得到结果count
.
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/>
并比较结果,看看这个方法是否可靠。
您不必更改 table 中的列类型即可使用 XML 查询,您可以使用 XMLQuery 或 XML表.
一种选择是使用XML表提取所有相关节点,并计算返回的节点数:
select count(*)
from your_table
cross join xmltable(
'//targetNodeName'
passing xmltype(clobtype_column_withXMLs)
columns dummy varchar2(1) path '@dummy'
);
XML表为每个匹配节点生成一行。由于您只对它们进行计数,而不使用该节点的内容,因此我使用了虚拟列名称和内容,选择了一个可能不存在的属性名称——如果可能,将其更改为其他名称。 dummy
值因此将为空,但 count(*)
无论如何都会计算它们。
当然必须测试它的性能如何……它可能比使用正则表达式更糟糕。不过,它会允许您搜索自闭标签,根据您当前正在做的事情,这对您来说可能无关紧要。
如果有用的话,您还可以调整它以计算原始 table 中每个 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;