Edited at

Lucene Index 考察(4)

More than 3 years have passed since last update.


概要

インデックスと関連する二つのコマンド(option)を検証します。


  • expungeDeletes

  • prepareCommit


expungeDeletes

Lucene Index 考察(2)で、deleteでドキュメントを削除してもインデックスに残され、その削除フラグだけ別途保存していることを確認していました。

ドキュメントが実際削除されるのはoptimizeコマンドでセグメントファイルをひとつにまとめる際でした。

commit時にexpungeDeletesをtrueに指定すると、deleteでドキュメントをインデックスから完全に削除してくれます(しかもoptimizeより軽く)。

これでインデックスサイズの削減と検索時メモリ消費を抑えることができます。もう一つのメリットは適切なスコアを計算してくれるようになることです。

その理由は、インデックスに削除済みドキュメントが残っていると、不本意にidf値計算のファクタであるdocFreqとmaxDocに削除済みドキュメントも含まれてしまうからです。

実際確認してみましょう。


  • 1segmentに2document登録し、その一つを削除してみます。

まず、2documentを登録します。

登録用XMLファイル test-2add.xml

$ cat test-2add.xml

<add>
<doc>
<field name="id">USD</field>
<field name="name">One Dollar</field>
<field name="manu">Bank of America</field>
<field name="manu_id_s">boa</field>
<field name="cat">currency</field>
<field name="cat">USD</field>
<field name="features">Coins and notes</field>
<field name="price_c">1,USD</field>
<field name="inStock">true</field>
</doc>
<doc>
<field name="id">EUR</field>
<field name="name">One Euro</field>
<field name="manu">European Union</field>
<field name="manu_id_s">eu</field>
<field name="cat">currency</field>
<field name="cat">EUR</field>
<field name="features">Coins and notes</field>
<field name="price_c">1,EUR</field>
<field name="inStock">true</field>
</doc>
</add>


  • dataディレクトリを削除し、solr起動

$ rm -Rf $SOLR_HOME/collection1/data

$ java -jar start.jar


  • add

$ curl http://localhost:8983/solr/collection1/update?commit=true -H "Content-Type: text/xml" --data-binary @test-2add.xml 


  • dataディレクトリを確認


$ ls -lRi $SOLR_HOME/collection1/data

total 0
30612265 drwxr-xr-x 15 mingchunzhao staff 510 1 29 06:55 index
30612269 drwxr-xr-x 3 mingchunzhao staff 102 1 29 06:55 tlog

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/index:
total 96
30612285 -rw-r--r-- 1 mingchunzhao staff 206 1 29 06:55 _0.fdt
30612281 -rw-r--r-- 1 mingchunzhao staff 63 1 29 06:55 _0.fdx
30612277 -rw-r--r-- 1 mingchunzhao staff 1211 1 29 06:55 _0.fnm
30612280 -rw-r--r-- 1 mingchunzhao staff 42 1 29 06:55 _0.nvd
30612283 -rw-r--r-- 1 mingchunzhao staff 81 1 29 06:55 _0.nvm
30612282 -rw-r--r-- 1 mingchunzhao staff 334 1 29 06:55 _0.si
30612278 -rw-r--r-- 1 mingchunzhao staff 121 1 29 06:55 _0_Lucene41_0.doc
30612279 -rw-r--r-- 1 mingchunzhao staff 112 1 29 06:55 _0_Lucene41_0.pos
30612284 -rw-r--r-- 1 mingchunzhao staff 895 1 29 06:55 _0_Lucene41_0.tim
30612286 -rw-r--r-- 1 mingchunzhao staff 375 1 29 06:55 _0_Lucene41_0.tip
30612288 -rw-r--r-- 1 mingchunzhao staff 36 1 29 06:55 segments.gen
30612287 -rw-r--r-- 1 mingchunzhao staff 131 1 29 06:55 segments_2
30612266 -rw-r--r-- 1 mingchunzhao staff 0 1 29 06:54 write.lock

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/tlog:
total 8
30612276 -rw-r--r-- 1 mingchunzhao staff 338 1 29 06:55 tlog.0000000000000000000

フィールド値を確認すると、1segmentに2document(USD,EUR)含まれています。

$ od -c $SOLR_HOME/collection1/data/index/_0.fdt

0000000 ? 327 l 027 030 L u c e n e 4 1 S t o
0000020 r e d F i e l d s D a t a \0 \0 \0
0000040 002 200 200 001 002 \0 002 \0 \n \a 265 X 360 # \0 003
0000060 U S D \b \n O n e D o l l a r 030
0000100 017 B a n k o f A m e r i c a
0000120 ( 003 b o a 0 \b c u r r e n c y 0
0000140 1 \0 360 034 8 017 C o i n s a n d
0000160 n o t e s P 005 1 , U S D X 001 T d
0000200 024 263 ( 246 177 @ \0 \0 \0 003 E U R \b \b Z
0000220 \0 ` E u r o 030 016 006 \0 350 p e a n
0000240 U n i o n ( 002 e u V \0 ? E U R V
0000260 \0 002 3 E U R V \0 P 246 201 240 \0 \0 300 (
0000300 223 350 \0 \0 \0 \0 \0 \0 \0 \0 222 337 245 ~


  • id="USD"のdocumentを削除します。

削除用XMLファイル test-del1.xml

$ cat test-del1.xml

<delete>
<id>USD</id>
</delete>


  • 全件取得してみます。確かに2件ヒットします。

$ curl "http://localhost:8983/solr/collection1/select?q=*:*&fl=id,\[docid\]&indent=true"

<?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">8</int>
<lst name="params">
<str name="fl">id,[docid]</str>
<str name="indent">true</str>
<str name="q">*:*</str>
</lst>
</lst>
<result name="response" numFound="2" start="0">
<doc>
<str name="id">USD</str>
<int name="[docid]">0</int></doc>
<doc>
<str name="id">EUR</str>
<int name="[docid]">1</int></doc>
</result>
</response>


  • delete

commitの属性としてexpungeDeletes=trueを指定します。

$ curl 'http://localhost:8983/solr/collection1/update?commit=true&expungeDeletes=true' -H "Content-Type: text/xml" --data-binary @test-del1.xml 


  • 再度全件取得して見ると、USDが削除されています。

$ curl "http://localhost:8983/solr/collection1/select?q=*:*&fl=id,\[docid\]&indent=true"

<?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">16</int>
<lst name="params">
<str name="fl">id,[docid]</str>
<str name="indent">true</str>
<str name="q">*:*</str>
</lst>
</lst>
<result name="response" numFound="1" start="0">
<doc>
<str name="id">EUR</str>
<int name="[docid]">0</int></doc>
</result>
</response>


  • dataディレクトリを確認

    Lucene Index 考察(2)で、expungeDeletes=trueを指定せずdeleteを行った場合、

    削除フラグを格納する .delファイルが追加されていましたが、今回は見当たりません。

    segment情報(segments.gen、segments_3)が変わりました。

$ ls -lRi $SOLR_HOME/collection1/data

total 0
30613015 drwxr-xr-x 15 mingchunzhao staff 510 1 29 07:50 index
30613019 drwxr-xr-x 4 mingchunzhao staff 136 1 29 07:50 tlog

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/index:
total 96
30613050 -rw-r--r-- 1 mingchunzhao staff 145 1 29 07:50 _1.fdt
30613046 -rw-r--r-- 1 mingchunzhao staff 63 1 29 07:50 _1.fdx
30613055 -rw-r--r-- 1 mingchunzhao staff 1211 1 29 07:50 _1.fnm
30613053 -rw-r--r-- 1 mingchunzhao staff 42 1 29 07:50 _1.nvd
30613048 -rw-r--r-- 1 mingchunzhao staff 81 1 29 07:50 _1.nvm
30613051 -rw-r--r-- 1 mingchunzhao staff 371 1 29 07:50 _1.si
30613049 -rw-r--r-- 1 mingchunzhao staff 83 1 29 07:50 _1_Lucene41_0.doc
30613047 -rw-r--r-- 1 mingchunzhao staff 80 1 29 07:50 _1_Lucene41_0.pos
30613052 -rw-r--r-- 1 mingchunzhao staff 749 1 29 07:50 _1_Lucene41_0.tim
30613054 -rw-r--r-- 1 mingchunzhao staff 375 1 29 07:50 _1_Lucene41_0.tip
30613057 -rw-r--r-- 1 mingchunzhao staff 36 1 29 07:50 segments.gen
30613056 -rw-r--r-- 1 mingchunzhao staff 131 1 29 07:50 segments_3
30613016 -rw-r--r-- 1 mingchunzhao staff 0 1 29 07:49 write.lock

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/tlog:
total 16
30613029 -rw-r--r-- 1 mingchunzhao staff 338 1 29 07:50 tlog.0000000000000000000
30613045 -rw-r--r-- 1 mingchunzhao staff 68 1 29 07:50 tlog.0000000000000000001

フィールド値を確認すると、segment_3に1 document(EUR)しか残っておらず、ドキュメントから完全に取り除いてくれたことがうかがえます。

$ od -c $SOLR_HOME/collection1/data/index/_1.fdt

0000000 ? 327 l 027 030 L u c e n e 4 1 S t o
0000020 r e d F i e l d s D a t a \0 \0 \0
0000040 002 200 200 001 002 \0 001 \n V 360 002 \0 003 E U R
0000060 \b \b O n e E u r o 030 016 006 \0 360 \n
0000100 p e a n U n i o n ( 002 e u 0 \b
0000120 c u r r e n c y 0 - \0 360 025 8 017 C
0000140 o i n s a n d n o t e s P 005
0000160 1 , E U R X 001 T d 024 263 + 312 316 200 \0
0000200 \0 300 ( 223 350 \0 \0 \0 \0 \0 \0 \0 \0 k ; k
0000220 N


prepareCommit

Solrのexpert-level APIでLuceneのIndexWriter.prepareCommit()をコールしています。


2フレーズcommitの中の第一フレーズのみ実施し、commit処理のほとんどをやってくれますが、インデックスから参照はできません。(commitは内部でprepareCommitを呼んでいます)


prepareCommitが失敗した場合、rollbackできます。

特に使う場面がないので運用で気にする必要はありませんが、一応確認してみます。


  • まず、1document登録します。

登録用XMLファイル test-add1.xml

$ cat test-add1.xml

<add>
<doc>
<field name="id">USD</field>
<field name="name">One Dollar</field>
<field name="manu">Bank of America</field>
<field name="manu_id_s">boa</field>
<field name="cat">currency</field>
<field name="cat">USD</field>
<field name="features">Coins and notes</field>
<field name="price_c">1,USD</field>
<field name="inStock">true</field>
</doc>
</add>


  • dataディレクトリを削除し、solr起動

$ rm -Rf $SOLR_HOME/collection1/data

$ java -jar start.jar


  • add

$ curl http://localhost:8983/solr/collection1/update -H "Content-Type: text/xml" --data-binary @test-add1.xml 


  • dataディレクトリを確認

segment情報のみで関連ファイルはできていません(commitがまだなので)。

$ ls -lRi $SOLR_HOME/collection1/data

total 0
30666535 drwxr-xr-x 5 mingchunzhao staff 170 1 29 13:48 index
30666539 drwxr-xr-x 3 mingchunzhao staff 102 1 29 13:49 tlog

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/index:
total 16
30666538 -rw-r--r-- 1 mingchunzhao staff 36 1 29 13:48 segments.gen
30666537 -rw-r--r-- 1 mingchunzhao staff 53 1 29 13:48 segments_1
30666536 -rw-r--r-- 1 mingchunzhao staff 0 1 29 13:48 write.lock

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/tlog:
total 8
30666545 -rw-r--r-- 1 mingchunzhao staff 205 1 29 13:49 tlog.0000000000000000000


  • prepareCommit

$ curl http://localhost:8983/solr/collection1/update?prepareCommit=true


  • dataディレクトリを確認

通常commitすると、segments_1がsegments_2にインクリメントされますが、まだ変わっていません。

但し、その他各種ファイルはできあがっているように見えます。

$ ls -lRi $SOLR_HOME/collection1/data

total 0
30666535 drwxr-xr-x 15 mingchunzhao staff 510 1 29 13:49 index
30666539 drwxr-xr-x 3 mingchunzhao staff 102 1 29 13:49 tlog

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/index:
total 96
30666564 -rw-r--r-- 1 mingchunzhao staff 149 1 29 13:49 _0.fdt
30666560 -rw-r--r-- 1 mingchunzhao staff 63 1 29 13:49 _0.fdx
30666556 -rw-r--r-- 1 mingchunzhao staff 1211 1 29 13:49 _0.fnm
30666559 -rw-r--r-- 1 mingchunzhao staff 42 1 29 13:49 _0.nvd
30666562 -rw-r--r-- 1 mingchunzhao staff 81 1 29 13:49 _0.nvm
30666561 -rw-r--r-- 1 mingchunzhao staff 334 1 29 13:49 _0.si
30666557 -rw-r--r-- 1 mingchunzhao staff 83 1 29 13:49 _0_Lucene41_0.doc
30666558 -rw-r--r-- 1 mingchunzhao staff 82 1 29 13:49 _0_Lucene41_0.pos
30666563 -rw-r--r-- 1 mingchunzhao staff 771 1 29 13:49 _0_Lucene41_0.tim
30666565 -rw-r--r-- 1 mingchunzhao staff 375 1 29 13:49 _0_Lucene41_0.tip
30666538 -rw-r--r-- 1 mingchunzhao staff 36 1 29 13:48 segments.gen
30666537 -rw-r--r-- 1 mingchunzhao staff 53 1 29 13:48 segments_1
30666536 -rw-r--r-- 1 mingchunzhao staff 0 1 29 13:48 write.lock

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/tlog:
total 8
30666545 -rw-r--r-- 1 mingchunzhao staff 205 1 29 13:49 tlog.0000000000000000000


  • フィールド値を確認すると、USDのドキュメントが格納されています。

$ od -c $SOLR_HOME/collection1/data/index/_0.fdt

0000000 ? 327 l 027 030 L u c e n e 4 1 S t o
0000020 r e d F i e l d s D a t a \0 \0 \0
0000040 002 200 200 001 002 \0 001 \n Z 360 # \0 003 U S D
0000060 \b \n O n e D o l l a r 030 017 B a
0000100 n k o f A m e r i c a ( 003 b
0000120 o a 0 \b c u r r e n c y 0 1 \0 025
0000140 025 8 017 C o i n s a n d n o t
0000160 e s P 005 1 , U S D X 001 T d 024 263 -
0000200 L 236 300 \0 \0 300 ( 223 350 \0 \0 \0 \0 \0 \0 \0
0000220 \0 267 371 O 202


  • 問題はここで検索可能でしょうか?

全件取得をやってみます。

残念ながら検索にはヒットしません。

$ curl "http://localhost:8983/solr/collection1/select?q=*:*&fl=id,\[docid\]&indent=true"

<?xml version="1.0" encoding="UTF-8"?>
<response>

<lst name="responseHeader">
<int name="status">0</int>
<int name="QTime">2</int>
<lst name="params">
<str name="fl">id,[docid]</str>
<str name="indent">true</str>
<str name="q">*:*</str>
</lst>
</lst>
<result name="response" numFound="0" start="0">
</result>
</response>


  • rollback

この時点でロールバック可能です。

$ curl http://localhost:8983/solr/collection1/update?rollback=true


  • dataディレクトリを確認

各種ファイルが消えています。

$ ls -lRi $SOLR_HOME/collection1/data

total 0
30666535 drwxr-xr-x 5 mingchunzhao staff 170 1 29 13:54 index
30666539 drwxr-xr-x 3 mingchunzhao staff 102 1 29 13:49 tlog

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/index:
total 16
30666538 -rw-r--r-- 1 mingchunzhao staff 36 1 29 13:48 segments.gen
30666537 -rw-r--r-- 1 mingchunzhao staff 53 1 29 13:48 segments_1
30666536 -rw-r--r-- 1 mingchunzhao staff 0 1 29 13:48 write.lock

/Users/mingchunzhao/blog/solr-4.10.2/example/solr/collection1/data/tlog:
total 8
30666545 -rw-r--r-- 1 mingchunzhao staff 205 1 29 13:49 tlog.0000000000000000000


次回

次回はインデックスに関係するSolrの各種パラメータを検証してみます。お楽しみに。