LoginSignup
3
3

More than 3 years have passed since last update.

Solr8系のセグメントのマージの動作とsolrconfig.xmlの設定について(SolrCloud)

Last updated at Posted at 2020-11-08

検証した環境

  • Solr:8.6(Cloud シャード:1,NRT:2)

環境構築編

セグメント(Segment)とは

Solrはコミットをするとインデックスに書き込みをします、内部的にはセグメントと呼ばれる単位で分割されています。
Segmentはインデックスを更新してコミットを実行するたびに新しいセグメントが作成されます。

例1

100件のドキュメントを登録してコミットする

スクリーンショット 2020-11-08 14.24.35(2).png

パラメータ 数値
Num Docs 100
MaxDoc 100
Deleted Docs 0
Segment Count 1

_0 -> docs:100, dels:0

更に30件新規のドキュメントを登録してコミットする

スクリーンショット 2020-11-08 14.35.22(2).png

パラメータ 数値
Num Docs 130
MaxDoc 130
Deleted Docs 0
Segment Count 2

_0 -> docs:100, dels:0
_1 -> docs:30, dels:0

あとから登録した30件は_1のセグメントに含まれます。

例2

次は100件登録してコミットしたあとに30件のドキュメントを更新してコミットしてみます。

スクリーンショット 2020-11-08 14.42.58(2).png

パラメータ 数値
Num Docs 100
MaxDoc 130
Deleted Docs 30
Segment Count 2

_0 -> docs:100, dels:30
_1 -> docs:30, dels:0

ドキュメントの更新の場合は0のセグメントのうち、1のセグメントに含まれるドキュメントは削除済みとして扱われます。

セグメントのマージ

ドキュメントの追加、更新、削除を繰り返すとセグメント数が増えていきます。
セグメント数が多くなると検索性能が劣化していきます。
また例2の場合のように削除済みとしてマークされているものは検索時には使用されないですがディスク上に残ってしまうので無駄になってしまいます。
なのでsolrではセグメントをマージする機能があります。

セグメントのマージ方法

  1. optimizeによる強制マージ
  2. コミット時にMergePolicyによるマージ
  3. expungeDeletesによるマージ

optimizeによる強制マージ

※ optimizeによる強制マージはあまり推奨されていないようです。 MergePolicyを利用したマージを使うほうが主流のようです。

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8981/solr/{collection}/update' --data-binary '
{
  "optimize": {maxSegments:1}
}'

MergePolicyによるマージ

今回はデフォルトのマージポリシーのTieredMergePolicyについてまとめます。

マージに関連するsolrconfig.xmlの設定

solrconfig.xml
<config>
  <indexConfig>
        <mergePolicyFactory class="org.apache.solr.index.TieredMergePolicyFactory">
          <int name="segmentsPerTier">10</int>
          <int name="floorSegmentMB">2</int>
          <int name="deletesPctAllowed">33</int>
          <int name="maxMergedSegmentMB">5000</int>
          <int name="maxMergeAtOnce">10</int>
          <int name="forceMergeDeletesPctAllowed">10</int>
        </mergePolicyFactory>
  </indexConfig>
</config>

マージのしきい値となる設定

segmentsPerTier(デフォルト値:10)

階層のSegment Countがしきい値(allowedSegCount)の設定値を超えると、次回のコミット時にマージが実行されます

SegmentCount > allowedSegCount

スクリーンショット 2020-11-08 15.17.50(2).png

デフォルトの10だとSegment Countが11になるとしきい値を超えるので次のコミット時にマージされます。
(※ドキュメントのトータルのサイズが小さい時)

スクリーンショット 2020-11-08 15.18.26(2).png

「0」から「9」がマージされbになる

allowedSegCountの算出方法

TieredMergePolicyでは以下のロジックでallowedSegCountが決定します。

    final int mergeFactor = (int) Math.min(maxMergeAtOnce, segsPerTier);
    long levelSize = Math.max(minSegmentBytes, floorSegmentBytes);
    long bytesLeft = totIndexBytes;
    double allowedSegCount = 0;
    while (true) {
      final double segCountLevel = bytesLeft / (double) levelSize;
      if (segCountLevel < segsPerTier || levelSize == maxMergedSegmentBytes) {
        allowedSegCount += Math.ceil(segCountLevel);
        break;
      }
      allowedSegCount += segsPerTier;
      bytesLeft -= segsPerTier * levelSize;
      levelSize = Math.min(maxMergedSegmentBytes, levelSize * mergeFactor);
    }
    allowedSegCount = Math.max(allowedSegCount, segsPerTier);
floorSegmentBytes = floorSegmentMB * 1024 * 1024

solrconfig.xmlで指定できる、floorSegmentMBの値を上げるとallowedSegCountの値も上がりにくくなります。

floorSegmentMB=1と設定した場合

スクリーンショット 2020-11-09 11.54.34.png

ドキュメントのトータルサイズが、10MBを超えるとallowedSegCount=12に変化します。

deletesPctAllowed(デフォルト値:33)

Deletionsの割合がdeletesPctAllowedを超えると、次回のコミット時にマージが実行されます

Deletions = \frac{Deleted Docs}{MaxDoc} * 100 > deletesPctAllowed

スクリーンショット 2020-11-08 15.28.11(2).png

スクリーンショット 2020-11-08 15.29.25(2).png

33%超えるとピンク色になるので次回のコミット時にマージされるのがわかります。

マージするセグメント数の設定

maxMergeAtOnce(デフォルト値:10)

マージが実行されるときにmaxMergeAtOnceの値までのセグメントがマージの対象となります

maxMergeAtOnce=2,maxMergedSegmentMB=5000の場合

スクリーンショット 2020-11-08 15.39.31(2).png

マージ対象がmaxMergeAtOnceの0,1だけが対象となります。

maxMergedSegmentMB(デフォルト値:5000)

マージが実行されるときにマージするセグメントの合計サイズがmaxMergedSegmentMBを超えない範囲が対象となります。

maxMergeAtOnce=10,maxMergedSegmentMB=1の場合

スクリーンショット 2020-11-08 15.50.40(2).png

この場合は0から4までがmaxMergedSegmentMBの値に収まるのでマージの対象となっていることがわかります。

expungeDeletes

コミット時にexpungeDeletesというのを指定することができます。

curl -X POST -H 'Content-Type: application/json' 'http://localhost:8981/solr/{collection}/update' --data-binary '
{
  "commit": {expungeDeletes: true}
}'

expungeDeletesを指定すると削除済みが含まれるセグメントがマージされます。
このときセグメント単体でみた削除のドキュメントの割合がforceMergeDeletesPctAllowed以下の場合は対象外となります。

スクリーンショット 2020-11-08 15.57.33(2).png

expungeDeletesを実行

スクリーンショット 2020-11-08 15.58.03(2).png

削除を含むセグメント0と1がマージされ4になりました。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3