オープンソースの検索エンジン Sphinx について調べたメモ
注意点としては
- 日本語は UTF-8 一択
- 検索対象 DB も UTF-8 だと楽
- Ngram のみ
- インデックスの部分的な更新に難あり
- blog, ニュース, フォーラムといった蓄積型のコンテンツには良い
- 更新柔軟性よりパフォーマンスやスケールを取っている
- 今後、別方式のインデックスを実装するプランはある
ライセンスは GPL v2 or 商用(embeded 用)
概要
ドキュメント を読んだメモ。
検索
document は複数の field を持ち、また検索用メタ情報である attribute を持つ。
field は検索に用いられる index 対象となるフィールドであり、Sphinx はこのフィールドを複数個持てる(デフォで上限32個?)
attribute はソートや、グルーピング、検索結果の絞り込みに使われる。詳細は 3.2 Attributes 参照。
検索モード
マッチングモード(ドキュメントの実例を見た方が早い)
- ALL: 全てを含む(デフォルト)
- ANY: いずれかを含む
- PHRASE: クエリをフレーズと見なす、perfect match(語順等)
- BOOLEAN: and, or, not, grouping 演算子が使える
- EXTENDED2: internal query。 @* hello 等
- FULL_SCAN:
以下は読み飛ばした。こんな機能もあるよ、程度に列挙
- weighting, sorting mode, grouping (clustering)
- distributed searching
- multi-server, multi-cpu, multi-core
- 水平分割して割り振る
インデックス
- 現在は"高速で、更新コストが極めて高い"タイプのインデックスのみ利用可能
- 将来的に、検索速度の代わりに更新に利便性のあるインデックスなど、インデックスタイプを選択できる予定らしい
live update は極めてコストが高く、構築し直しとさほど変わりない。
代案としてインデックスを分割する方法がある。
- 更新頻度の高いインデックス
- ほぼ不変のインデックス
と二つに分けて、更新コストや影響を区切る。
詳細は 3.10. Live index updates にある。
また index の統合については 3.11. index merging にある。
例にある SQL では初回インデックス生成時 (main) の MAX(id) をカウンタテーブルに保存しておき、それ以降のデータソース/インデックスは delta として扱うような内容になっている。
- インデックスを分割した際のデメリットやパフォーマンスの低下については未発見。
- 例にあるように今までの投稿 + 新しい投稿といった足し込んでいけるものは main+delta に index merging を使って対処出来そうだが、全体に更新がかかるようなものはどうするのが良いか不明
- 実は例示が極端なだけで、データ量が少なければインデックスを再生成しまくれるのかも知れない。
データソース
Sphinx が検索対象とするデータ、または検索インデックスを作成する元データをデータソースという。
Sphinx がデータソースにアクセスするためのコードをデータドライバという。
データソースの制限
- ドキュメントID必須、ID は一意であり、unsigned non-zero integer numbers である事
- 32bit or 64bit は build time setting で指定
Sphinx のデータドライバは
- sql driver
- xmlpipe
sql driver には ranged query 機能があり、1,000 件単位で処理する等して、ロックとメモリ消費を現実的な範囲に落とす事が出来る。
データソース生成時には文字変換テーブルが使える
- インデックス作成時に charset table を参照し、データソースの変換を行う。
- 例えば Abc, abc, ABC は検索語、データソースがいずれであってもヒット可能となる。
- English & Russian しかないので、おまいらの書いた変換テーブルがあればコミットしてね!との事。
MySQL protocol & SphinQL
SELECT * FROM test1 WHERE MATCH('test');
etc
filter
- 例: ENG で検索した後、model=3 に絞る
- 値の複数指定は可能
- 範囲指定可能
$ /usr/local/bin/search \ --config /usr/local/etc/sphinx.conf --filter model 3 ENG index 'catalog': query 'ENG ': returned 1 matches of 1 total in 0.000 sec displaying matches: 1. document=9, weight=1, assembly=5, model=3 id=9 partno=ENG976 description=Large cylinder head price=65 words: 1. 'eng': 2 documents, 2 hits