2017-11-16 17 views
0

CLOB型の列にある特定のXMLノードをカウントするための最適化されたSQLクエリを作成しようとしていましたが、今はREGEXP_COUNTを使用してすべての行とすべてのXMLしかし、これはひどく遅いです。このようOracle SQL - Clob型の列のXMLノードをカウントする

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

これは動作しますが、タグの数百万でそれは文字通りの年齢を取ります。

私はXML構造を回避し、カウント時間を短縮したいと考えています。私は何かを見つけましたが、それらのほとんどは列の型をxmlに変更し、xqueryと他のDML関数を使用します。
私の場合、私はテーブルを変更することはできません、私は数だけ、指定されたノードが列に発生する回数が必要です。

マイテーブル構造:

ないXML表、各種カラムタイプとすべての行は、異なるサイズのXML(文字の数百万)を含有するCLOB type column、。 XMLはかなり複雑な構造を持っている、私が探しています1つのノードが真ん中にあります。

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

は、表には何も変更せずに、このような構造のノードをカウントする任意の高速な方法はありますか?速いとは、は数時間で最大5億ノードをカウントします。

+0

を '「私はいくつかのことを発見したが、それらのほとんどは、XMLに列タイプを変更伴い、XQueryおよび他のDML機能を使用しています。」'、あなたの答えを見つけるだから – lad2025

+0

"私の場合、テーブルを変更できません" – DragonTester

+0

XQueryを使用するためにテーブルの列の種類を変更する必要はありません。オンザフライでの変換、抽出、カウントが現在行っている処理より速いかどうかを実験する必要があります。 –

答えて

1

あなたはXMLを解析しなければならない要素をカウント同じ精度でREGEXP_COUNT(必要はないのと同じ結果にあなたのためのトリックshoudl仕事を交換し、測定長さの差(テキスト検索は、24時間+かかります)究極の精度)。

REPLACEアプローチの利点は、最も高速な実装になります。

単純

  • NULL

  • と元の文字列で検索サブストリングの各発生を置き換える元の文字列の長さの差と置換された1つの

  • 除算計算結果の数を得るための部分文字列の長さの結果

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/> 

を使用していくつかのテストを行い、このimethodが信頼できるかどうかを確認するために結果を比較するためにお勧めしたいです。

+0

ありがとうございました!私は間違いなくこれをテストするでしょう、私は自分自身の出力を短縮するなどの同様のことを試みましたが、この組み合わせは決して私には起こりませんでした。 – DragonTester

+0

ありがとう、これは魅力のように私の20 +時間の選択はわずか47分かかりました。 – DragonTester

0

XMLクエリを使用できるようにテーブルの列の種類を変更する必要はありません。XMLQueryまたはXMLTableを使用してオンザフライで変換できます。

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

のXMLTableが一致する各ノードに対して1つの行を生成します。

1つのオプションは、あなたが戻って取得する方法多くの関連のすべてのノードを抽出し、カウントするの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; 
+0

ありがとうございました!私はこれより小さなサンプルサイズで試してみます。これは私が探していたものですが、最後の行(x xmltype path '。')を理解できません。この部分はXMLTABLE関数ですか? – DragonTester

+0

@DragonTesterはい; 'targetNodeName'ノード(あなた自身の実際の名前をもちろん使用します)を、特別な理由なしに' x'という出力のXMLTypeカラムに入れています。通常、選択リストのその列を参照します。ここでも、よりわかりやすい名前を使用できます。しかし、XMLTableから出力された行を数え、ノードの内容は無視しても問題ありません。私はXMLTypeを作成しました。なぜなら、 'varchar2'に収まるかどうかわからないからです。 –

+0

@DragonTester - 実際、必要以上に多くのリソースを使用するでしょう。ノードのダミー属性からダミー値を使用するように変更しました。それでも無視されますが、メモリ使用量は少なくなります。 –

関連する問題