Feb 26, 2009

[PostgreSQL] Ludia にチャレンジ

Ludia とは

Ludiaは高速かつ高精度な全文検索インデックス機能をオープンソースのデータベース管理システムであるPostgreSQLに提供します。Ludia は株式会社NTTデータにより開発され、2006年10月11日にLGPLライセンスのオープンソースソフトウェアとして公開されました。
ということで、PostgreSQLに全文検索機能付加するソフトウェア。 Senna, MeCab との連携機能を PostgreSQL に追加してくれる。 全文検索エンジン(Lucene とか Hyper Estraier とか)を管理する手間が省けるので、中小規模の全文検索が必要な場合にはとても便利そうだ。
Ludia
http://sourceforge.jp/projects/ludia/
Senna
http://qwik.jp/senna/FrontPageJ.html
MeCab
http://mecab.sourceforge.net/

Ludia のインストール

Ludia 1.5.1 を Mac OS X (Leopard) + PostgreSQL 8.3 にインストールしてみた。

Senna のインストール

まずは Ludia の動作に必要な Senna をインストール。 今回は MeCab は使用しない (Ludia で わかち書き に対応しない) ので、いきなり Senna をインストールする。 MeCab を使用する場合は先に MeCab をインストールする。

$ wget http://osdn.dl.sourceforge.jp/senna/33763/senna-1.1.4.tar.gz
--2009-02-26 00:00:48--  http://osdn.dl.sourceforge.jp/senna/33763/senna-1.1.4.tar.gz
  (SNIP)
2009-02-26 00:00:48 (2.59 MB/s) - `senna-1.1.4.tar.gz.1' へ保存完了 [1121030/1121030]

$ tar zxvf ./senna-1.1.4.tar.gz 
senna-1.1.4/
senna-1.1.4/lib/
senna-1.1.4/lib/nfkc.h
  (SNIP)

$ cd ./senna-1.1.4
$ ./configure --without-mecab
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... ./install-sh -c -d
checking for gawk... no
  (SNIP)
  Install path prefix:   /usr/local

Now type 'make' to build senna 1.1.4!

$ make
make  all-recursive
Making all in lib
  (SNIP)
creating hatenapo
make[2]: Nothing to be done for `all-am'.

$ sudo make install | tee ./install.log
Password:
Making install in lib
test -z "/usr/local/lib" || .././install-sh -c -d "/usr/local/lib"
 /bin/sh ../libtool   --mode=install /usr/bin/install -c  'libsenna.la' '/usr/local/lib/libsenna.la'
  (SNIP)
 /usr/bin/install -c -m 644 'senna.pc' '/usr/local/lib/pkgconfig/senna.pc'
test -z "/usr/local/include/senna" || ./install-sh -c -d "/usr/local/include/senna"
 /usr/bin/install -c -m 644 'senna.h' '/usr/local/include/senna/senna.h'
$ 

Ludia のインストール

Senna がインストール出来たら、次に Ludia をインストール。 MacPorts を使用して PostgreSQL をインストールしている場合は、PostgreSQL のパスを指定する必要がある。

$ wget http://globalbase.dl.sourceforge.jp/ludia/32461/ludia-1.5.1.tar.gz
--2009-02-26 00:21:24--  http://globalbase.dl.sourceforge.jp/ludia/32461/ludia-1.5.1.tar.gz
  (SNIP)
2009-02-26 00:21:25 (1.37 MB/s) - `ludia-1.5.1.tar.gz' へ保存完了 [421128/421128]

$ tar zxvf ./ludia-1.5.1.tar.gz 
ludia-1.5.1/
ludia-1.5.1/ltmain.sh
ludia-1.5.1/README.advanced
  (SNIP)
ludia-1.5.1/README
ludia-1.5.1/Makefile.in

$ ./configure --with-pg-config=/opt/local/lib/postgresql83/bin/pg_config --with-senna-cfg=/usr/local/bin/senna-cfg 
checking build system type... i686-apple-darwin9.6.0
checking host system type... i686-apple-darwin9.6.0
checking for gcc... gcc
checking for C compiler default output file name... a.out
  (SNIP)
config.status: creating pgsenna2.h
config.status: creating config.h
config.status: executing depfiles commands

$ make
make  all-am
if /bin/sh ./libtool --mode=compile --tag=CC gcc -D_REENTRANT -I. -I. -I.   -DPOSTGRES83=1 
-I/opt/local/include/postgresql83 -I/opt/local/include/postgresql83/server -I/usr/local/
include/senna  -Wall -fno-strict-aliasing -g -O2 -MT pgsenna2.lo -MD -MP -MF ".deps/
pgsenna2.Tpo" -c -o pgsenna2.lo pgsenna2.c;  
  (SNIP)
	elif [ `expr -- "-DPOSTGRES83=1 -I/opt/local/include/postgresql83 -I/opt/local/include/
postgresql83/server -I/usr/local/include/senna " : .*POSTGRES81.*` -gt 0 ]; then 
	  cp -f ./uninstall_pgsenna2_81.sql.in ./uninstall_pgsenna2.sql; 
	fi
$ sudo make install | tee ./install.log
Password:
test -z "/opt/local/lib/postgresql83" || /Users/me/Desktop/ludiawork/ludia-1.5.1/install-sh 
-d "/opt/local/lib/postgresql83"
 /bin/sh ./libtool --mode=install /usr/bin/install -c  'pgsenna2.la' '/opt/local/lib/
postgresql83/pgsenna2.la'
/usr/bin/install -c .libs/pgsenna2.0.0.0.so /opt/local/lib/postgresql83/pgsenna2.0.0.0.so
(cd /opt/local/lib/postgresql83 && rm -f pgsenna2.0.so && ln -s pgsenna2.0.0.0.so pgsenna2.0.so)
(cd /opt/local/lib/postgresql83 && rm -f pgsenna2.so && ln -s pgsenna2.0.0.0.so pgsenna2.so)
/usr/bin/install -c .libs/pgsenna2.lai /opt/local/lib/postgresql83/pgsenna2.la
/usr/bin/install -c .libs/pgsenna2.a /opt/local/lib/postgresql83/pgsenna2.a
ranlib /opt/local/lib/postgresql83/pgsenna2.a
ranlib: file: /opt/local/lib/postgresql83/pgsenna2.a(pgs2_tp.o) has no symbols
ranlib: file: /opt/local/lib/postgresql83/pgsenna2.a(pgs2_recovery.o) has no symbols
chmod 644 /opt/local/lib/postgresql83/pgsenna2.a
----------------------------------------------------------------------
Libraries have been installed in:
   /opt/local/lib/postgresql83

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `DYLD_LIBRARY_PATH' environment variable
     during execution

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------
test -z "/opt/local/share/postgresql83" || /Users/me/Desktop/ludiawork/ludia-1.5.1/install-sh -d "/opt/local/share/postgresql83"
 /usr/bin/install -c -m 644 'pgsenna2.sql' '/opt/local/share/postgresql83/pgsenna2.sql'
 /usr/bin/install -c -m 644 'uninstall_pgsenna2.sql' '/opt/local/share/postgresql83/uninstall_pgsenna2.sql'

$ /opt/local/lib/postgresql83/bin/psql -U me -f ./pgsenna2.sql mydb
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
  (SNIP)
CREATE OPERATOR CLASS
CREATE OPERATOR CLASS
CREATE OPERATOR CLASS
$ 
これで Ludia のインストールは全て完了。次は設定。

Ludia の設定

Ludia の初期設定を行う。 Ludia の設定は postgresql.conf に記述する。

$ sudo cp /opt/local/var/db/postgresql83/mydb/postgresql.conf /opt/local/var/db/postgresql83/mydb/postgresql.conf.original
$ sudo vi /opt/local/var/db/postgresql83/mydb/postgresql.confPassword:

$ sudo diff /opt/local/var/db/postgresql83/mydb/postgresql.conf.original /opt/local/var/db/postgresql83/mydb/postgresql.conf
493a494,508
> 
> #------------------------------------------------------------------------------
> # LUDIA OPTIONS
> #------------------------------------------------------------------------------
> 
> custom_variable_classes = 'ludia'
> ludia.max_n_sort_result = 10000
> ludia.enable_seqscan = on
> ludia.seqscan_flags = 1
> ludia.sen_index_flags = 3
> ludia.max_n_index_cache = 16
> ludia.initial_n_segments = 512
$ 

postgresql.conf の編集が完了したら、PostgreSQL を再起動する。

$ sudo -u postgres /opt/local/lib/postgresql83/bin/pg_ctl -D /opt/local/var/db/postgresql83/mydb restart
waiting for server to shut down.... done
server stopped
server starting
$ 

Ludia の動作確認

PostgreSQL に組み込まれた Ludia と Senna のバージョンを確認する。

$ /opt/local/lib/postgresql83/bin/psql -U me mydb
Welcome to psql 8.3.0, the PostgreSQL interactive terminal.
  (SNIP)
mydb=# SELECT pgs2version();
 pgs2version 
-------------
 ludia 1.5.1
(1 row)

mydb=# SELECT version, configure_option FROM pgs2seninfo();
 version |  configure_option  
---------+--------------------
 1.1.4   |  '--without-mecab'
(1 row)

mydb=#

テストに使用するテーブルと Ludia 用のインデックスを作成する。

mydb=# create table LUDIA_TEST (ID bigint primary key, VALUE text);
CREATE TABLE

mydb=# create index LUDIA_TEST on DATA using fulltext(VALUE);
CREATE INDEX
インデックス作成で指定している "using fulltext(VALUE)" は、"カラム VALUE を形態素解析でインデクシングする"という意味。 形態素解析以外にも、N-gram や空白区切りも使用可能。

Ludia を使って全文検索を行ってみる。 PostgreSQL 8.2 以前を使用している場合はクエリの記法が異なるので注意(下のクエリでは '%%' を '@@' に置き換える)。

mydb=# insert into LUDIA_TEST (ID, VALUE) values (1, 'トタンがセンベイ食べて 春の日の夕暮は穏かです アンダースローされた灰が蒼ざめて 春の日の夕暮は静かです');

mydb=# select * from LUDIA_TEST where VALUE %% '夕暮';
 id | value 
----+----------------------------------------------------------------------------------------
 1  | トタンがセンベイ食べて 春の日の夕暮は穏かです アンダースローされた灰が蒼ざめて 春の日の夕暮は静かです
(1 row)

mydb=#