k.log

2009-06-16

[]Solr のメモリ使用量を小さくする

Solr で使われるメモリを減らす必要がある場合に僕がとりあえず考えることを挙げます.以下の内容は僕の Solr 1.3 での経験に基づいてますが,おそらく次期版の 1.4 でも同じではないかと思います.

キャッシュを小さくする

Solr はメモリ上に検索結果をキャッシュする機構を持っています.これは検索性能を向上するのにとても役立ちますが,メモリを食います.

キャッシュは (Solrコアのホームディレクトリ)/conf/solrconfig.xml で定義され,サイズを指定することができます.

Solr のキャッシュは何種類かあり,自分で用意することもできますが,たとえば元から用意されており世話になる可能性が高い filterCache は,Solr 添付の example 内の solrconfig.xml で次のように定義されています:

<filterCache class="solr.LRUCache" size="512" initialSize="512" autowarmCount="128"/>

キャッシュの容量を小さくするには,size 属性の値を小さくします.initialSize や autowarmCount もそれに合わせて適宜変更します.

ちなみに,class 属性を見るとわかりますが,この場合は LRU 方式のキャッシュを使います(Solr で用意しているのは LRU のみ*1).つまり,キャッシュの容量がいっぱいになったとき,参照されていない時間の長い値から順にキャッシュを追い出されます.一方で,頻繁に参照される値はキャッシュ内に残りやすいと言えます.キャッシュサイズを調整するときはこうした点も考慮に含めると良いと思います.たとえば,多くの場合に決まった数個〜数十個のキャッシュが使われれば十分な性能が得られるような場合(性別や都道府県でフィルタリングするとか)は 512 個のキャッシュ容量は不要かもしれません.

キャッシュされた値の数やヒット率などの情報を,Solr の管理ページ(admin/stats.jsp#cache) から確認できます.こうした情報を元に,たとえば役に立っていないキャッシュは思い切って無効にしてしまう(solrconfig.xml からキャッシュの設定を削除)のも良いでしょう.

参考:

サーバを検索用と更新用に分ける

多くの検索と更新が行われるようであれば,メモリに限らず CPU使用率やディスクI/Oなどの状況をみてサーバを検索用と更新用にわけた方がいいと思います.

検索のリアルタイム性が高く要求されるようなケースでなければ,基本的には RDBMS でよくやるような Master-Slave の構成にするのが良いでしょう.Master-Slave 構成をするにあたって,Solr 1.3 には ssh + rsync を使ったレプリケーションが bash スクリプトで用意されています.また,1.4 からは HTTP を使ったレプリケーション機能が Solr 本体に組み込まれています.

ちなみに 1.3 までの,外部スクリプトを使ったレプリケーションはおそらく Windows では動きません.

参考:

ソートを変える

Solr(というか Lucene かな) は検索結果のソートが得意ではありません.遅いし余分にメモリを使います.100万件の検索結果はあまりソートしたくありません.

明示的にソートをせずに検索結果の順位を制御できないか,ソートするフィールドが String のときは int や float で代替できないか,フィールドの cardinality を下げられないか等を検討すると良いでしょう.

ソートに関するメモリ使用量については Lucene の JavaDoc に情報があります:

*1:他のアルゴリズムを自分で用意したい場合は org.apache.solr.search.SolrCache を実装する