【MarkLogic Server】繰り返し要素を用いたXML集約によるデータサイズ低減効果

はじめに
===
今回は、複数のXMLファイルを1個にまとめることによってMarkLogicが利用するディスク容量が低減されるのか？ということについてみていきたいと思います。

背景
===
ディスクの価格が下がっているとはいえ、データサイズが小さいに越したことはありません。そこで、XMLデータの持ち方を工夫することでディスク量を減らしてみる方法について検証してみます。

今回は、１個のXMLファイルに対して
・1個のデータを格納する場合と、
・複数のデータを繰り返し要素を用いて格納する場合とで
MarkLogicにおけるデータベースサイズを比較してみます。

繰り返し要素とは
===
ここで繰り返し要素の設定というのは、以下のように複数のデータを1個のXMLにまとめることを意味します。以下のデータを例に見てみましょう。(a, b, c)={(A1, B1, C1), (A2, B2, C2)}の2組のデータがある場合、XMLでは1組ずつXMLファイルとするか、2組で1個のXMLファイルとするかといったパターンが考えられます。今回の検証では、後者の繰り返し度合いをパラメータとして変動してみます。

```
1組ずつ2個のXMLとする          繰り返し要素repeatで集約したXMLとする
-------------------          --------------------------------
<testDocument>               <testDocument>
  <a>A1</a>                    <repeat>
  <b>B1</b>                      <a>A1</a>
  <c>C1</c>                      <b>B1</b>
<testDocument>                   <c>C1</c>
----------------               </repeat>
<testDocument>                 <repeat>
  <a>A2</a>                      <a>A2</a>
  <b>B2</b>                      <b>B2</b>
  <c>C2</c>                      <c>C2</c>
</testDocument>                </repeat>
                             </testDocument> 
```

一応、繰り返し要素を設定した場合、以下のような弊害あることも挙げておきましょう。
・前処理によって複数データを1個のXMLファイルにする必要が生じる。
・繰り返し要素の設定によって、同一ドキュメント内の異なるデータに対する更新の排他制御ができなくなる。

このため繰り返し要素の設定は、以下のようなケースが適していると言えます。
・バッチ処理など、一定のデータ数をまとめることができる。即時性が低い。
・複数の更新が同時に走りにくい、極めて静的なデータである。

実機検証
===

では実際にサンプルデータを作り、MarkLogicに入れてデータサイズを測ってみます。

| 対象MarkLogicバージョン |
|---|
|8.0-3.3|

サンプルデータは、1データに54要素でこのうち3要素にelement range索引を設定しました。各データは、それぞれ異なる20文字の要素値を持ちます。これを100万データ分作成しました。実際の過程ではCSVファイル(100万行で合計1.055GB)をまず作って、そこから以下のようなXMLファイル(合計で概ね3GB)を作成しています。

```
<testDocument>
  <repeat>
    <key1>Tjr5v8Ye_000000000001</key1>
    <key2>0ZCIjYAg_000000000001</key2>
    <key3>EdnTwU9F_000000000001</key3>
    ・・・ (51要素) ・・・
  </repeat>
  <repeat>
    ・・・ (54要素) ・・・
  <repeat>
    ・・・・・・
<testDocument>    
```

さて、1XML内の繰り返し数を順次変更しつつドキュメント挿入した時のMLDBデータサイズは以下のようになりました。なおケース①は繰り返し要素を設定しないものです。倍率は 挿入後データサイズ ÷ 挿入前XML総サイズです。

| ケース | 1XML内の繰り返し数 | XMLファイル数 | 挿入前XML総サイズ | 挿入後データサイズ | 倍率 |
|---|---|---|---|---|---|
| ① | 1     | 100万 | 3.069 GB | 30 GB | 9.775 |
| ② | 10    | 10万  | 3.033 GB | 23 GB | 7.538 |
| ③ | 100   | 1万   | 3.016 GB | 19 GB | 6.300 |
| ④ | 1,000 | 1,000 | 3.000 GB | 11 GB | 3.667 |

ケース①ではほぼ10倍にも上り、サンプルデータはデータサイズが大きくなりやすいものだったと推定します。繰り返し要素を設定しないケース①に対して、ケース②～④の倍率が低下していることから同設定によるデータサイズの減少が確認できました。試しにEXCELでグラフを描いてみたのが以下です。

![repeatElementGraph2.jpg](https://qiita-image-store.s3.amazonaws.com/0/188643/256379f5-a751-b20f-9139-10c61be89927.jpeg)


1→10→100→1,000と10倍ずつ設定しているわけですから、繰り返し数の増加に対して対数関数的に減少していると言えます。繰り返し数を大きくしていけば、やがては元のXML総サイズと同じくらいになると考えられます。

考察
===
データサイズの低減に寄与するのは、XML数そのものの減少にあります。MarkLogicではドキュメントごとにフラグメントが作成されます。固定的なサイズを持つフラグメント数の減少が、そのままデータサイズの減少に寄与したと考えられます。

おわりに
===
繰り返し要素の設定によりデータサイズの低減を確認できたものの、今回の方法は検索性能の観点から繰り返し数を大きくしすぎるのも限度があると考えられます。
実は、MarkLogic社ウェブサイトでは1個のXMLサイズは10KB～100KB程度が最適としています。1個のXMLサイズ = 挿入前XML総サイズ ÷ XMLファイル数　という計算式から、この教えに従えばケース②30KBまたは③300KB位が妥当なラインだったと言えます。
参考：https://docs.marklogic.com/guide/cluster/scalability

今後、積極的にバージョンアップを繰り返しているMarkLogic自身が内部の圧縮索引アルゴリズムを改善して、繰り返し要素を設定しなくてもデータサイズを小さくすることを期待したいと思います。

```math
\def\textsmall#1{%
  {\rm\scriptsize #1}
}
```

------------------------------------------------------------------------

**免責事項**

​​​​​$\textsmall{当ユーザ会は本文書及びその内容に関して、いかなる保証もするものではありません。}$
​​​​​$\textsmall{万一、本文書の内容に誤りがあった場合でも当ユーザ会は一切責任を負いかねます。}$
​​​​​$\textsmall{また、本文書に記載されている事項は予告なしに変更または削除されることがありますので、予めご了承ください。}$