PostgreSQL Ludiaインストールメモ

PostgreSQL全文検索、Ludiaインストールメモ。

PostgreSQL8.3.3以前のDBで運用しているLudiaのインストールと注意点に関するメモ。

参考サイト
http://sourceforge.jp/projects/ludia/
http://ludia.sourceforge.jp/cgi-bin/moin.cgi/

対応環境

PostgreSQL : 8.1.10, 8.2系(8.3.3でも動作は確認。それ以降ではパッチをあてる必要があるため、素直にtextsearch_sennaを使うことをお勧めします)

MeCab : ludia-withdeps-1.5.1.tar.gzの場合、同梱されています

Senna : ludia-withdeps-1.5.1.tar.gzの場合、同梱されています

インストール手順

PostgreSQLはインストール済みだとします。
PostgreSQLコンパイルディレクトリは「/usr/local/src/postgresql-8.3.3」だとします。
PostgreSQLのインストールディレクトリは「/usr/local/pgsql」だとします。
・モジュールのバージョンは適宜よみかえてください。

Ludiaのダウンロードと解凍

PGXSを使いたくないので、contribの下で作業します。

cd /usr/local/src
wget http://sourceforge.jp/projects/ludia/downloads/32462/ludia-withdeps-1.5.1.tar.gz
tar zxf ludia-withdeps-1.5.1.tar.gz -C /usr/local/src/postgresql-8.3.3/contrib/
Mecabインストール

形態素解析で使用するMecabをインストールします。
ここでは、EUC-JPを使用します。

cd /usr/local/src/postgresql-8.3.3/contrib/ludia-1.5.1/deps
tar zxf mecab-0.97.tar.gz
cd mecab-0.97
./configure --with-charset=euc-jp
make

su -
cd /usr/local/src/postgresql-8.3.3/contrib/ludia-1.5.1/deps/mecab-0.97
make install
exit
Mecab辞書をインストール
cd /usr/local/src/postgresql-8.3.3/contrib/ludia-1.5.1/deps/
tar zxf mecab-ipadic-2.7.0-20070801.tar.gz
cd mecab-ipadic-2.7.0-20070801
./configure --with-charset=euc-jp
make

su -
cd /usr/local/src/postgresql-8.3.3/contrib/ludia-1.5.1/deps/mecab-ipadic-2.7.0-20070801
make install
exit
Sennaインストール

Ngram方式の全文検索エンジンSennaをインストールします。

cd /usr/local/src/postgresql-8.3.3/contrib/ludia-1.5.1/deps
tar zxf senna-1.1.3.tar.gz
cd senna-1.1.3
./configure
make

su -
cd /usr/local/src/postgresql-8.3.3/contrib/ludia-1.5.1/senna-1.1.3
make install
exit
Ludiaインストール

本体をインストールします。

cd /usr/local/src/postgresql-8.3.3/contrib/ludia-1.5.1/
./configure
make

su -
cd /usr/local/src/ludia-1.5.1
make install
exit
Ludia設定

・インデックスアクセスメソッドの登録

psql -f /usr/local/pgsql/share/pgsenna2.sql DB名


PostgreSQLの設定ファイルpostgresql.confに全文検索用の設定を追加

postgresql.conf

#------------------------------------------------------------------------------
# CUSTOMIZED OPTIONS
#------------------------------------------------------------------------------

# list of custom variable class names
custom_variable_classes = 'ludia'
# 検索ヒット数の上限設定
ludia.max_n_sort_result = 10000
# ON :  シーケンシャルスキャンを実行できる
# OFF : シーケンシャルスキャンが実行された場合にエラー
ludia.enable_seqscan = on
# 0: 比較文字列を正規化せずに、シーケンシャルスキャンを行う
# 1: 比較文字列を正規化した後、シーケンシャルスキャンを行う
ludia.seqscan_flags = 1
# ludia.sen_index_flags = 19 (010011)
# fulltextuでインデックスを作成したときに有効となるフラグ。
# 1bit: 英文字の大文字/小文字、全角文字/半角文字を正規化
# 2bit: N-gramインデックスで正規化を指定した際、英文字列もn文字の要素に分割する
# 3bit: N-gramインデックスで正規化を指定した際、数字文字列もn文字の要素に分割する
# 4bit: N-gramインデックスで正規化を指定した際、記号文字列もn文字の要素に分割する
# 5bit: (形態素解析ではなく)n-gramを用いる
# 6bit: (形態素解析ではなく)空白区切りで単語を区切る
ludia.sen_index_flags = 19
# インデックスの同時オープン数の上限
ludia.max_n_index_cache = 16
# インデックスの初期サイズ
ludia.initial_n_segments = 512
su -
# 設定反映
/etc/init.d/postgres reload
exit

使い方

・インデックスアクセスメソッドの種類
 fulltext : 正規化 + 形態素解析 (SEN_INDEX_NORMALIZE)
 fulltextb : 正規化 + 2-gram (SEN_INDEX_NORMALIZE|SEN_INDEX_NGRAM)
 fulltextu : ユーザ定義
fulltexta : 配列型インデックス

・インデックスの作成
 こんな感じ

# fulltextで作成
CREATE INDEX index1 ON table1 USING fulltext(col1);

# マルチカラムインデックスをサポート
CREATE INDEX index2 ON table1 USING fulltext(col1 text, col2 text);

# 配列型インデックスをサポート
CREATE INDEX index3 ON table1 USING fulltexta ((ARRAY[col1, col2, col3]));

全文検索インデックスを使用した検索
8.3以降では、@@は予約語のため、%%で検索を行ってください。
「*D+」、「*W」などは、Sennaのクエリの書式に準拠します。

# hogeで
SELECT * FROM table1 WHERE col1 @@ 'hoge';

# ヒットスコアを表示する。ctidはそのテーブル内のタプルのタプルIDです。
SELECT col1, pgs2getscore(table1.ctid, 'index1') FROM table1 WHERE col1 @@ 'hoge';

# AND検索
SELECT * FROM table1 WHERE col1 @@ '*D+ hoge fuga';

# OR検索。配列型インデックスを利用するとOR検索を高速に行うことができます。
SELECT * FROM test WHERE ARRAY[col1, col2, col3] @@ 'piyo';

# 重み付け検索
SELECT *, pgs2getscore(ctid) AS score FROM test
WHERE array[col1, col2, col3] @@ '*W1:10,2:5,3:1 hello' ORDER BY score DESC;


・インデックスの削除
 インデックスを削除する場合、不要なファイルが残ってしまうため以下のように削除してください。

DROP INDEX 全文検索インデックス名;

CHECKPOINT;
SELECT pgs2destroy();

・設定内容の表示

SELECT * FROM pgs2getoption();

・インデックスの情報を取得

SELECT * FROM pgs2indexinfo();

注意点

・Ludiaがインデックス対象とできるのはtext型のみ

・vacuum
 vacuumを行うと、無効になったタプルに対するインデックス情報が残ってしまうため、インデックスの再作成が必要です。

vacuumdb -avz

psql -q ${DB_NAME} <<_EOD_
  DROP INDEX インデックス名;
  CHECKPOINT;
  SELECT pgs2destroy();
  CREATE INDEX index1 ON table1 USING fulltext(col1);
_EOD_