1

私は大きなxmlデータベース(30 000ファイル、1.3 Go)を持っています。このデータベースの1つのファイルには、データベースに存在する他のすべてのファイルが一覧表示されます。私の目的は、リストされているすべてのファイルがデータベースに存在するかどうかを「単に」チェックすることです。しかし、私はファイルの名前を気にする必要はなく、ドキュメント内のXMLコードだけを気にする必要があります。

これはそのようなものです:

declare variable $root :=  fn:collection();

declare function local:isValid($fileCode) {

let $fileSearchedIdentCode := $root/dmodule/identity/dmCode
return 
$fileCode/@attribute1 = $fileSearchedIdentCode/@attribute1 and
$fileCode/@attribute2 = $fileSearchedIdentCode/@attribute2 and
$fileCode/@attribute3 = $fileSearchedIdentCode/@attribute3

};

<result>
{ 
for $fileCode in $root/file[identity/@fileType eq 'listOfFiles']/fileContent/fileEntry/fileCode 
return
    if (local:isValid($fileCode))
    then   <filePresent>1</filePresent>  
    else <fileNonPresent>2</fileNonPresent>

}
</result>

上記のコードは小さなデータベースで実行されていますが、私の場合は、信じられないほどの時間が必要です。

だから、誰かが合理的な時間でそれを実行するためにそのコードを改善するのを手伝ってくれるのだろうか;)

(私のデータベースは索引付けされています)

ご協力いただきありがとうございます !!

ヨハン

4

5 に答える 5

3

関数の属性チェックに属性インデックスが適用されていないようlocal:isValidです。XPath述語としてそれらを書き直すことにより、これを実現できます。

declare variable $root :=  fn:collection();

declare function local:isValid($fileCode) {
  $root/dmodule/identity/dmCode[@attribute1 = $fileCode/@attribute1
    and @attribute2 = $fileCode/@attribute2
    and @attribute3 = $fileCode/@attribute3]
};

<result> { 
  for $fileCode in $root/file[identity/@fileType = 'listOfFiles']/fileContent/fileEntry/fileCode 
  return
    if (local:isValid($fileCode))
      then   <filePresent>1</filePresent>  
      else <fileNonPresent>2</fileNonPresent>
}</result>

これらの変更後、BaseXのクエリ情報ビューにインデックスが使用されていることが通知されます。

Compiling:
- pre-evaluating fn:collection()
- rewriting And expression to predicate(s)
- rewriting fn:boolean(@*:attribute1 = $fileCode/@attribute1)
- rewriting fn:boolean(@*:attribute2 = $fileCode/@attribute2)
- rewriting fn:boolean(@*:attribute3 = $fileCode/@attribute3)
- applying attribute index
- applying attribute index

テストデータの評価時間は4'500msから〜20msに減少します。

于 2012-02-13T15:46:35.817 に答える
3

MarkLogicの場合、インデックスルックアップは特定の式と関数でのみ発生することに注意する必要があります。この場合、よりコンパクトなコードが必要です。これは同じ結果を生成するはずのフォームですが、簡単な方法でインデックスを使用します。

<result>
{
    for $fileCode in
      collection()/
      file[identity/@fileType eq "listOfFiles"]/
      fileContent/
      fileEntry/
      fileCode
    let $fc1 := $fileCode/@attribute1/string()
    let $fc2 := $fileCode/@attribute2/string()
    let $fc3 := $fileCode/@attribute3/string()
    return
      if (collection()/
          dmodule/
          identity/
          dmCode[
            @attribute1 eq $fc1][
            @attribute2 eq $fc2][
            @attribute3 eq $fc3])
      then <filePresent>1</filePresent>
      else <fileNonPresent>2</fileNonPresent>
  }
</result>

listOfFilesただし、そのコードはエントリごとに1つのデータベースルックアップを実行しますが、これは最適ではありません。

さらに最適化することが可能です。まず、MarkLogicはドキュメント指向のデータベースであり、すべてのドキュメントに一意のURIがあります。したがって、3つの属性値を各ドキュメントURIに単純にエンコードすると、はるかに効率的になります。string-join(($fc1, $fc2, $fc3), '/')URIを構築するためにのようなものを使用するかもしれません。次に、呼び出しを使用して各値をチェックできますdoc()。これは、インデックスを使用している場合でも、XPathルックアップよりも効率的です。そして、その変更が行われると、listOfFilesドキュメントは属性値ではなくURIを格納することもできます。

第二に、結果の形式はあまり役に立たないと思います。一部のドキュメントが欠落しているが、どのドキュメントが欠落しているかはわかりません。コードが欠落しているドキュメントURIのみを返すようにリファクタリングします。MarkLogicで使用可能な追加のインデックスであるURIレキシコンを有効にすることもできます。これにより、ドキュメントのように、すべてのドキュメントURIの値インデックスが自動的に維持されますlistOfFiles。URIレキシコンを使用して、次のように書くことができます。

<result>{
    let $uris :=
      collection()/
      file[identity/@fileType eq "listOfFiles"]/
      fileContent/
      fileEntry/
      fileCode/
      string-join(
        (@attribute1/string(),
         @attribute2/string(),
         @attribute3/string()),
        "/")
    let $uris-present := cts:uris((), "document", cts:document-query($uris))
    for $uri in $uris
    where not($uri = $uris-present)
    return <missing>{ $uri }</missing>
}</result>

これには、データベースのルックアップが1つだけ必要であり、残りの必要な作業はメモリ内で行われます。元のクエリや最初の反復よりもはるかに優れたスケーリングが必要です。結果形式の私の作り直しに同意せず、それでもすべての入力の結果を表示したい場合は、元のクエリのように句をfileCodeリファクタリングできます。...where...return......return...if...then...else...

必ずhttps://github.com/marklogic/cqのプロファイルツールを使用してください。これは、代替案を試したり、最適化の機会を見つけたりするのに役立ちます。

于 2012-02-13T18:17:27.540 に答える
1

テストシステムのリストにeXist-dbを含めませんでしたが、データでベンチマークすることに興味がある場合は、クエリを最適化し、インデックスをインテリジェントに使用してeXist-dbのパフォーマンスを高速化することに関する優れた記事があります。http://exist-db.org/exist/tuning.xmlを参照してください。投稿したクエリは変更しなくても正常に機能するはずですが、記事のアドバイスは間違いなくパフォーマンスの向上に役立ちます。ヘルプが必要な場合は、既存のオープンメーリングリストに気軽に投稿してください。

どのシステムを使用する場合でも、私だけでなく、あなたの結果を知りたいと思います。幅広い関心があると思います。

幸運を!

于 2012-02-13T16:49:05.987 に答える
1

比較で使用している各属性に属性範囲インデックスを定義すると、MarkLogicはクエリを高速に処理する必要があります。

これは、MarkLogic管理UI(http:// hostname:8001)を介して実行できます。

  • [データベース]でデータベースを選択します
  • 左側の[属性範囲インデックス]を選択します
  • [追加]を選択して、新しい属性範囲インデックスを定義します
  • 範囲インデックスを参照して要素(dmcode)と属性(attribute1、attribute2、attribute3)を指定します(要素が特定の名前空間にある場合は、名前空間を指定することを忘れないでください)。
  • [OK]をクリックして、範囲インデックスを作成します。

どのバージョンのMarkLogicを使用していますか?MarkLogic 5を使用している場合は、クエリコンソールを使用してクエリをテストすることもできます。

(http://ホスト名:8000 / qconsole)

ご不明な点がございましたら、お気軽にお問い合わせください。私はMarkLogicの出身で、喜んでお手伝いします。

于 2012-02-13T20:38:49.637 に答える
0

「eq」を等号(=)に置き換えるのに役立ちますか?

于 2012-02-13T15:15:34.217 に答える