CSAを使った全文検索ライブラリtsubomiを公開してみる

しばらく前から作っていた全文検索ライブラリtsubomiを公開しておく。
本ライブラリは接尾辞配列(Suffix Array)というアルゴリズムを使っていて、入力として与えたキーワードを含む行をテキストデータから探して、その行と出現位置を取得できる。さらに圧縮接尾辞配列(Compressed Suffix Array)による圧縮もサポートしているのでインデックスサイズを小さく抑えることができる。
本ライブラリは検索のためのAPIのほかに、インデックス作成、圧縮、検索を行うツールが付属している。ツールを使うだけでも、ある程度のことができる。
以下、簡単に紹介。


tsubomiはGoogleCodeでコードを管理している。詳細は下記URLを参照。

http://code.google.com/p/tsubomi/

コード管理にはsubversionを使っているので

$$ svn checkout http://tsubomi.googlecode.com/svn/trunk/ tsubomi

としてコードを取得できる。なんらかの事情でsubversionが使えない場合は

$$ mkdir tsubomi
$$ cd tsubomi
$$ wget http://tsubomi.googlecode.com/files/tsubomi-2010-09-04.tgz
$$ tar xzfv tsubomi-2010-09-04.tgz

でtarballを入手&解凍して使うことができる。

コードを入手したら

$$ make
$$ sudo make install

でインストールする。

例えば、住所JP(http://jusyo.jp/)という住所データが入手できるサイトがあるので、ここからデータをとってきて使う。

$$ mkdir var
$$ cd var
$$ wget http://jusyo.jp/downloads/new/csv/csv_zenkoku.zip
$$ unzip csv_zenkoku.zip

$$ nkf -w zenkoku.txt > zenkoku.txt.utf8
$$ perl -ne '@a=split(/\t/);$s="$a[7]$a[9]$a[11]";$s=~s/"//g;print "$s\n"' zenkoku.txt.utf8 > zenkoku.key
$$ sort -u zenkoku.key -o zenkoku.key
$$ cd ..

今回は、住所データから「都道府県」「市区町村」「町域」の3列を繋げて1データとした。テキストデータはutf8を使うこと。

まずtsubomi_mkaryというコマンドでインデックスをつくる。

$$ tsubomi_mkary -p var/zenkoku.key

-pオプションを指定しておくとインデックス作成の進捗がバーで表示される。var/以下を見ると、zenkoku.key.aryというファイルが出来ているのがわかる。これがインデックス。

早速、検索を実行してみる。tsubomi_searchというコマンドを使う。

$$ tsubomi_search var/zenkoku.key
麻布
東京都港区麻布十番 : 15
東京都港区麻布台 : 15
...
東京都港区西麻布 : 18

キーワード麻布を含む行が表示された。「:」の後ろは出現位置がバイト単位で表示されている。

次にインデックスを圧縮してみる。tsubomi_mkcsaというコマンドを使う。

$$ tsubomi_mkcsa -p var/zenkoku.key

-pオプションに付いてはtsubomi_mkaryと同様。圧縮されたインデックスはzenkoku.key.csaという名前のファイルで保存されている。この圧縮インデックスはself-indexingというもので検索に元のテキストを必要としない。試しに、元テキストと圧縮していない方のインデックスを別の場所に移して正しく検索できるか確認。

$$ mkdir tmp
$$ mv var/zenkoku.key tmp/
$$ mv var/zenkoku.key.ary tmp/

$$ tsubomi_search -c var/zenkoku.key
麻布
東京都港区麻布十番 : 15
東京都港区麻布台 : 15
...
東京都港区西麻布 : 18

このように正しく検索できることがわかる。圧縮インデックスを使う場合は-cオプションを付ける。ちなみにデータサイズはというと

$$ ls -la var/zenkoku.key*
-rw-rw-r--. 1 xxxx xxxx  3869373 2010-09-04 10:10 zenkoku.key
-rw-rw-r--. 1 xxxx xxxx 15477492 2010-09-04 10:12 zenkoku.key.ary
-rw-rw-r--. 1 xxxx xxxx  6087740 2010-09-04 10:12 zenkoku.key.csa

となっていてzenkoku.key(元テキスト)とzenkoku.key.ary(インデックス)を併せて約19MBなのに対して、これらが圧縮されたzenkoku.key.csaは6MBなので1/3くらいに圧縮されている(tsubomi_mkcsaに、さらに圧縮率を上げるオプションがある。但し速度が犠牲になる)。

最後に実行速度についてだが、zenkoku.keyの各行をキーワードとして検索をした時にかかった時間を以下に示す(CPU:Core2Duo(1GHz) / Memory:500MB)。

$$ wc -l var/zenkoku.key
117957

$$ time tsubomi_search -c var/zenkoku.key < var/zenkoku.key > hogehoge
real	0m6.926s
user	0m1.473s
sys	0m4.998s

$$ time tsubomi_search -c var/zenkoku.key < var/zenkoku.key > hogehoge
real	2m53.556s
user	0m16.097s
sys	2m27.487s

圧縮しない場合は12万件で約7秒、圧縮した場合は約3分かかっている。圧縮した場合は約25倍の時間がかかる。
以上。解説はここまで。ライブラリのAPIについては別途解説予定。sadakane先生の高性能ライブラリがある昨今、あえてCSAライブラリを公開する必要があるのかとか色々あるんだけど、折角作ったので。。。元々自分の作業効率化のために作ったので、それなりに使いやすいはず。たぶん。