MySQL or PostgreSQL + Sennaのオススメ構成

Sennaの主な利用用途であると考えられる、
データベース組み込み用途。


ブラジル内部でもSennaを用いたサービスを運用していますが、
その運用ノウハウの一部をメモ。

  • Sennaはメモリ食い

Sennaはインデックスをメモリにマップすることによって
高速な追加・更新・削除を実現しています。
よって、メモリ使用量が多くなっています。


INITIAL_N_SEGMENTSを減らすことによって、
メモリ使用量を下げることができますが、
特に追加・更新においてパフォーマンスが低下します。


また、Linuxの場合、
空きメモリはI/Oキャッシュに割り当てられます。
Sennaのメモリ使用量が多いため、
I/Oキャッシュとして用いられるメモリ容量が減り、
結果としてシステム全体のパフォーマンスが落ちる場合があります。


MySQLのkey_buffer_sizeは、
Sennaと他のインデックスを組み合わせて利用する際に
重要となるチューニングパラメータです。
このkey_buffer用のメモリも必要となります。


さらにメモリが枯渇すると、
スラッシングを起こしてしまったり、
OOM Killerが動いて、
mysqldそのものが落ちてしまう可能性もあります。

Sennaトランザクションにも対応していません。
よって、トランザクションを利用するようなクエリで、
insert/updateのあとrollbackがかかった場合、
Sennaのインデックスにゴミが混じることがあります。


よって、MySQLやPgとSennaを組み合わせた検索エンジンを運用する場合には、

  • マスタのデータベースと、検索用のデータベースを分ける
  • マスタのデータベースから定期的に検索用のデータベースにデータをコピー
  • 検索用のデータベースのスキーマは、マスタのスキーマどおりではなく、検索に適したスキーマとする。場合によっては、正規化も崩す。特にMySQLの場合には、検索に必要なデータを全てまとまた、大きな1つの表を作成するのがいい。

といった運用がオススメです。


これで、Sennaによってメモリを食い尽くされることもなく、
トランザクションを利用したアプリケーションを作成することができ、
パフォーマンスも高い検索システムが出来上がります。


検索用のデータベースサーバは、
以下のようなスペックをオススメします。

  • メモリは多めに積む
    • メモリが多い場合は、INITIAL_N_SEGMENTSの値を増やすと特にインデックス追加・更新のパフォーマンスが向上
    • MySQLのkey_buffer_sizeは忘れずに設定する。これを設定しないと、他インデックスと全文検索との組み合わせでパフォーマンスが発揮されない
  • CPUはそれなりのコア数・速度があるものを選択
    • N-gram利用のほうがスケールしやすい
  • OSはamd64/em64t版で(メモリを多めに積むため・パフォーマンスが向上するため・mmapで仮想空間の枯渇を起こさないため)