1

スタイラススタジオ(DATA DIRECT付き)/ xQueryを使用して2つのxmlファイルを1つに結合します(ファイルは最初にCSVからxmlに変換されてから結合されます)。顧客(ヘッダー)データが最初に読み取られ、次に各顧客のトランザクションデータが読み取られます。(ループを使用)トランザクションデータもトランザクションの日付(年)ごとにグループ化されます。これは、別個の機能を使用して行われます。トランザクションデータファイルは非常に大きく、処理に非常に時間がかかります。パフォーマンスを向上させる方法を探しています。どんな助けでも。アドバイスは大いに評価されます。以下は使用されるコードです。ありがとう。

(:options:)
declare option ddtek:xml-streaming "yes";
declare option ddtek:serialize "encoding=UTF-8, 
               omit-xml-declaration=no, indent=yes";

(:external variables:)
declare variable $esa-h-converter as xs:string external;
declare variable $esa-t-converter as xs:string external;
declare variable $input-h-data-path as xs:string external;
declare variable $input-t-data-path as xs:string external;


(:main:)
<ROOT_NODE>
  {
    let $heads := doc(fn:concat(
                        "converter:", 
                        $esa-h-converter, 
                        "?file:///", 
                        $input-h-data-path))
                  /DATA_ROOT/CUSTOMER 

    for $record at $primaryKey in $heads

    return
      <TEMPLATE>
        <CUSTOMER>
          <RECORD_COUNT>{ $primaryKey }</RECORD_COUNT>
          <HD_REGION>{ $record/HD_REGION/text() }</HD_REGION>
          <HD_CONT>{ $record/HD_CONT/text() }</HD_CONT>
          <HD_FRDATE>{ $record/HD_FRDATE/text() }</HD_FRDATE>
          <HD_TODATE>{ $record/HD_TODATE/text() }</HD_TODATE>
          <HD_CUSNAME>{ $record/HD_CUSNAME/text() }</HD_CUSNAME>
          <HD_ADDR1>{ $record/HD_ADDR1/text() }</HD_ADDR1>
          <HD_ADDR2>{ $record/HD_ADDR2/text() }</HD_ADDR2>
          <HD_ADDR3>{ $record/HD_ADDR3/text() }</HD_ADDR3>
          <HD_ADDR4>{ $record/HD_ADDR4/text() }</HD_ADDR4>
          <HD_STATE>{ $record/HD_STATE/text() }</HD_STATE>
          <HD_SUBTOWN>{ $record/HD_SUBTOWN/text() }</HD_SUBTOWN>
          <HD_PCODE>{ $record/HD_PCODE/text() }</HD_PCODE>
          {

            let $my-transactions := 
                doc(fn:concat("converter:", 
                              $esa-t-converter, 
                              "?file:///", 
                              $input-t-data-path)) 
                              /DATA_ROOT
                              /TRANSACTION
                             [TR_CONT eq $record/HD_CONT 
                              and TR_REGION eq $record/HD_REGION]
            let $years := fn:distinct-values(
                           $my-transactions
                           /fn:substring(TR_DATE/text(), 1, 4))
            for $period in $years
            return
              <PERIOD>
                <RECORD_COUNT>{ $primaryKey }</RECORD_COUNT>
                <YEAR>{ $period }</YEAR>
                {
                  $my-transactions 
                  [fn:substring(TR_DATE/text(), 1, 4) = $period]
                }              
              </PERIOD>
          }
        </CUSTOMER>
      </TEMPLATE>
  }
</ROOT_NODE> 
4

1 に答える 1

1

パフォーマンスは通常、個々の製品や特定のデータに大きく依存するため、ここで得たすべてのアドバイスを信用する前に自分でテストしてください。私より Data Direct のプロセッサに詳しい方が、あなたの質問に答えてくれることを願っています。しかし、そうは言っても、試してみる価値のあることがいくつか思い浮かびます。

  • 最初にトランザクション ファイルを顧客別に並べ替えてから、マージを実行してみてください。トランザクション ファイルが長い場合、並べ替えは高速ではありません。

  • メイン ファイルの各レコードにアクセスしてそのトランザクションを検索する代わりに、(顧客ごとに編成されたトランザクション ファイルが与えられた場合) トランザクション ファイル内の各顧客にアクセスして、マージを実行することができます。

  • あなたの内部 FLWOR 式は、トランザクション ファイル全体で 2 つの選択を行っています。これには、fn:substring(TR_DATE/text(), 1, 4)ほとんどすべての XQuery エンジンのオプティマイザが無効になる可能性が非常に高いようです。エンジンが日付でインデックスを作成した場合、部分文字列を調べることで、クエリ プロセッサが値に対して単純なインデックス ルックアップを実行できないことを確認できますが、インデックス内のすべての値 (またはドキュメント内のすべての値) をスキャンする必要があります。 ) 一致の場合。

    両方のファイルの XML を作成していると言うので、その年の部分文字列を抽出して (冗長に) 別の要素または属性に入れることができると思います。これにより、原則として、XQuery エンジンがインデックスを作成し、スキャンの代わりにインデックス ルックアップを使用して選択のその部分を実行できるようになります。(それが特定のプロセッサで役立つかどうかはわかりません。)

于 2013-02-10T20:02:34.683 に答える