PostgreSQLで検証用Webサーバーを作って色々とWebサイト作りの練習をしているとふと、今はDBに格納されているテストデータが少ないから良いもののもし大量のデータを蓄積した状態になったとすると、このサイトはちゃんとしたパフォーマンスを発揮するのだろうか、と気になった。アンテナサイトの作り方シリーズで紹介しているアンテナサイトもアクセスが伸び悩んでいるのはデータベースの肥大化によるレスポンスの悪さからくるものだと反省しきりであることも、この疑問を思い当たるに至った動機の一つである。しかしながら海外で開発されているデータベースは、2byte文字であらわされる言語の検索がとても苦手である。そもそもアルファベットだけで構成されて、しかも単語が一つ一つスペースで区切られている欧米の多くの言語をメインに考えられているため、単語がスペースで区切られず文字の数も膨大な2byte文字を使用する日本語の検索は、それ用の創意工夫を挟まねば、欧米言語用の仕組みをそのまま適応するととても非効率になってしまい、思ったほどのパフォーマンスを得られない。前方一致検索や後方一致検索ならさくっとインデックスが使えるのに対し、中間一致検索では色々工夫しないとインデックスが使えずとてもじゃないけど待ってられないよってほどに待たされちゃったりするのだ。
PostgreSQLでの日本語中間一致検索方法の選択肢
では、PostgreSQLにおいて日本語の中間一致検索で現実的なパフォーマンスを得る方法はあるのか?実はたくさんある。
- textsearch_ja+MeCab (形態素解析)
- textsearch_senna (N-Gram方式)
- textsearch_groonga (N-Gram方式、スカラー値検索)
- pg_trgm (Tri-Gram方式)
- pg_bigm (Bi-Gram方式)
最初のtextsearch_ja+MeCab、textsearch_senna、textsearch_groongaの3つは、PostgreSQLコミュニティーのpgFoundryの中のtextsearch-jaプロジェクトによって開発されている。MeCabや、Senna、groongaといった外部モジュールをPostgreSQLに組み込むためのものだ。MeCabや、groongaは現在でも活発に更新されおり、日本語検索を考える上でとっても魅力的なのだが、textsearch-jaプロジェクトは残念ながらあんまり活発ではないらしく、各ソフトウェアの最終更新が1年や2年前のものが多い。なので今回はおいておくことにしたい。
pg_trgm?は、PostgreSQLのcontribの中に入っているTri-Gram方式のインデックスを使えるようにするモジュールだ。contribさえインストールしてしまえば使えそうだが、実はデフォルトのパッケージでは対象を半角英数字に限定するマクロがKEEPONLYALNUMオプションとして有効になっており、日本語で使うにはソースコードをKEEPONLYALNUMオプションを外した状態に編集してPostgreSQL本体をコンパイルしインストールしなおす必要がある。また、3文字ごとに文字を区切って検索するTri-Gram方式なので2文字や1文字の検索ではpg_trgm?は働いてくれない。この辺りは以下のサイトを参考にさせていただいた。
テキスト検索の方法とインデックス(Let’s Postgres)
2011-02-28N-gram全文検索 in PG9.1(PostgreSQL 雑記)
最後のpg_bigm?は、Bi-Gramを使ってインデックスを作成する。どうやら公式HPの右下のコピーライトから察するにNTT-DATAが作ってるみたいだが、ライセンスはThe PostgreSQL Licenceライセンスだそうである。pg_bigm?のインストールはpg_bigm?だけをコンパイルしてインストールすればいい。pg_trgm?のように本体をコンパイルしなおしたりする必要はないのでお手軽である。さらに、2文字ずつ文字列を解析するBi-Gram方式を使っているため、1文字、2文字の検索の場合でもちゃんとインデックスが使用される。
以上より、今回はpg_trgm?とpg_bigm?を使えるようにしてみる。pg_trgm?とpg_bigm?は同じDBで同時に使用することはできないので注意が必要だ。DB毎にどちらで使うかを決めておく必要がある。また、モジュールのビルドはビルドのみに必要で普段は使わないソフトウェアをたくさんインストールしてしまうことになる。セキュリティー上、いらぬセキュリティーホールを抱えてしまうことの無いよう、本番環境は必要な最小構成にしておくことが好ましい。ビルドにはビルド用の環境を用意することが望ましい。今回は検証環境での作業なのでその辺は気にしない手順になっている。実際の手順は次回、詳しく述べてみることにする。