CreateField Blog

オープンソースを使って個人でWebサービスを開発・運営していたブログ

専門用語を自動抽出するTermExtractをDockerで簡単に使えるようにしました

はじめに

品詞のつながりや出現頻度、学習情報から複合語らしきキーワードを自動で抽出するPerlモジュールTermExtractが公開されています。

これを利用すれば、形態素解析済みのテキストを食わせるだけでそこそこそれらしい専門用語をたくさん得ることができます。

このTermExtractは、ソースからインストールする必要があったり、EUC環境であったり形態素解析後のデータを入力に必要としたりなかなかめんどくさいです。

そこで、MeCabとTermExtractが自動で環境構築されるDockerファイルを作りました。

https://github.com/naoa/docker-termextract

このDockerファイルでは、正規表現フィルタや形態素解析、コスト推定などを自動でやってくれるPerlスクリプトも自動で導入されるようになっています。

これでDockerを実行できる環境があれば、プレーンなテキストをパイプでdocker runコマンドに渡すだけで、簡単に専門用語を抽出することができます。

また、形態素解析辞書の出力形式も用意しているので、出力結果を簡単に形態素解析辞書に組み込むこともできます。

Dockerのインストール

Dockerが入っていない場合、まずはDockerをインストールしてください。Dockerは今結構旬なプロダクトなので導入に困ることはないんじゃないかなと思います。 CentOSならepelリポジトリを有効にしてyum install -y docker-ioだけで導入できます。

イメージ構築

まずは、Dockerイメージを作成します。コンテナとファイル共有するために/var/lib/termextractディレクトリを作成しています。

% git clone git@github.com:naoa/docker-termextract.git
% cd docker-termextract
% mkdir /var/lib/termextract
% docker build -t naoa/termextract .

Docker上のTermExtractを実行して専門用語を抽出

echoコマンドやcatコマンドを使って、パイプ越しにプレーンテキストをdocker runコマンドに渡します。

% echo "印刷用紙を複合機で印刷する。" | \ 
  docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl
複合機                                298.54
印刷用紙                              14.01

Dockerコンテナ内に環境構築済みのTermExtractによって、「複合機」と「印刷用紙」という複合語を得ることができました。

数値は、重要度を示しています。学習機能を自動でオンにしているため、複数回実行すると重要度はどんどんあがっていきます。学習機能の詳細は本家サイトをご確認ください。学習用のDBは、/var/lib/termextract/stat.db/var/lib/termextract/comb.dbに作成されます。分野を変える場合やリセットする場合は、ファイルを移動するなり削除するなりしてください。

7/10追記

コマンドが長くてめんどくさいですが、エイリアスをはれば短縮できます。常用的に使う場合は、~/.bashrcなどの起動スクリプトに書けばよいです。

% alias termextract="docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl"

正規表現フィルタ

TermExtractでは、品詞のつながりや出現頻度、学習情報から複合語らしきものを結合しようとします。しかしながら機械的な処理なので誤って結合されることも結構あります。

形態素解析前にプレーンテキストから除去する文字列の正規表現パターンが記載されたファイル/var/lib/termextract/pre_filter.txtと、複合語抽出後に除外させる正規表現パターンが記載されたファイル/var/lib/termextract/post_filter.txtを用意しています。 TermExtractを実行しながらこれらのファイルを編集して適宜フィルタルールを調整することにより極力ノイズを減らすことができます。

出力形式

出力形式には、以下のように専門用語と重要度を出力してくれるモード、直接、IPAdic辞書の形式で出力してくれるモードを用意しています。

--output 説明
1 または 引数なし 専門用語+重要度
2 専門用語のみ
3 カンマ区切り
4 IPAdic辞書形式(自動コスト推定)
5 IPAdic辞書形式(文字列長)

せっかく自動コスト推定までしてくれる環境を作ったので、ついでにTermExtractを使わずに行ごとの単語リストをコスト推定してくれるモードも用意しています。

オプション 説明
--no_term_extract 専門用語抽出せずにコスト推定のみ実行

IPAdic辞書形式(自動コスト推定)

--output 4を指定するとMeCabで自動コスト推定したIPAdic形式の文字列が出力されます。

% echo "印刷用紙を複合機で印刷する。" | \
  docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl --output 4
複合機,1285,1285,7336,名詞,一般,*,*,*,*,複合機,*,*,ByTermExtractEst
印刷用紙,1285,1285,7336,名詞,一般,*,*,*,*,印刷用紙,*,*,ByTermExtractEst

これを利用すれば、プレーンテキストを入力するだけで、自動コスト推定までしたIPAdic辞書を簡単に追加することができます。

なお、自動コスト推定のアルゴリズムはよくわかっていませんが、自動推定によって追加した用語は推定コストが割り振られているため文脈によっては必ず区切られるとは限りません。

既存の形態素解析結果を極力壊したくない場合は、こちらを利用する方がいいかもしれません。

GroongaやElasticsearch、Solrなどの全文検索では、単語の前後の出現位置もマッチさせる完全転置索引方式をとっているため、コストを考慮せずに単純に用語を追加しただけの辞書を用いると検索漏れが多くなる惧れがあります。 全文検索では極力精度がおちないように慎重にチューニングするかNgramと併用するなど工夫が必要です。

MeCabには、既存の学習済みモデルと少量の学習データ(1行分の正解の形態素解析結果ぐらい)を使った再学習機能も備わっています。

再学習機能は、少量とはいえ自前で正解の形態素解析結果をつくる必要があるため、多数の用語ごとに学習データを準備するのはかなり大変です。しかし、ちゃんとドメイン適応したい場合は多少工数をかけてでも手動で学習モデルをつくったほうがいいかもしれません。

IPAdic辞書形式(文字列長)

--output 5を指定すると文字列長に応じてコストが設定されたIPAdic形式の文字列が出力されます。

% echo "印刷用紙を複合機で印刷する。" | \
  docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl --output 5 
複合機,0,0,-14500,名詞,一般,*,*,*,*,複合機,*,*,ByTermExtractLen
印刷用紙,0,0,-16000,名詞,一般,*,*,*,*,印刷用紙,*,*,ByTermExtractLen

これを利用すれば、プレーンテキストを入力するだけで、用語の文字列長に応じてコストが極端に低くなるように設定されたIPAdic辞書を簡単に追加することができます。

この場合、ほぼ既存の形態素解析辞書のコストよりも低くなるため、文脈によらず追加した用語が優先的に切りだされるようになります。

なお、この方法はすでに存在する用語を押しのけて切り出されるようになるので、短い用語や一般的な用語を追加するのはお勧めできません。

テキストマイニング系では多少の誤りは統計的に淘汰されることにより影響が低いと思われますので、多少ノイズがあっても専門用語を多数追加したほうがよい結果が得られるかもしれません。

IPAdic辞書形式(複合語抽出なし)

--no_term_extractを指定すると形態素解析、専門用語抽出をせずにMeCabで自動コスト推定したIPAdic形式の文字列が出力されます。

% echo "印刷用紙" | docker run -v /var/lib/termextract:/var/lib/termextract \
  -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl --no_term_extract
印刷用紙,1285,1285,7336,名詞,一般,*,*,*,*,印刷用紙,*,*,ByMeCabEst

その他のオプション

その他、出力件数や重要度の閾値等を設定することができます。TermExtractのサンプルスクリプトにある設定項目はほぼすべてコマンドオプションにマッピングしています。 詳しくは、GitHubを参考にしてください。

MeCab辞書への追加

形態素解析速度を損なわないように、システム辞書へ追加することをおすすめします。

システム辞書への追加は、辞書ソースフォルダに辞書形式のテキストファイルを設置して再ビルドします。 なお、追加辞書ファイルの文字コードに注意です。このDockerの環境では、utf-8でテキストが書き出されるのでeuc-jpに戻す必要があります。

自動コスト推定した辞書の追加例

% docker run -v /var/lib/termextract:/var/lib/termextract -i -t naoa/termextract /bin/bash
% echo "印刷用紙を複合機で印刷する。" | termextract_mecab.pl --output 4 > /mecab-ipadic-2.7.0-20070801/user.csv
% cd /mecab-ipadic-2.7.0-20070801
% nkf -e --overwrite user.csv
% make clean
% ./configure --with-charset=utf8; make; make install
# echo "印刷用紙を複合機で印刷する。" | mecab
印刷用紙        名詞,一般,*,*,*,*,印刷用紙,*,*,ByTermExtractEst
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
複合    名詞,サ変接続,*,*,*,*,複合,フクゴウ,フクゴー
機      名詞,接尾,一般,*,*,*,機,キ,キ
で      助詞,格助詞,一般,*,*,*,で,デ,デ
印刷    名詞,サ変接続,*,*,*,*,印刷,インサツ,インサツ
する    動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
。      記号,句点,*,*,*,*,。,。,。
EOS

「印刷用紙」と「複合機」を追加していますが、「複合機」では分割されませんでしたね。MeCabの自動コスト推定の結果によって設定されたコストでは、この文脈では分割されませんでした。この文脈で正しく分割して欲しい場合は、正解の形態素解析結果を作って再学習させる必要があります。

文字列長に応じた低コスト辞書の追加例

% docker run -v /var/lib/termextract:/var/lib/termextract -i -t naoa/termextract /bin/bash
% echo "印刷用紙を複合機で印刷する。" | termextract_mecab.pl --output 5 > /mecab-ipadic-2.7.0-20070801/user.csv
% cd /mecab-ipadic-2.7.0-20070801
% nkf -e --overwrite user.csv
% make clean
% ./configure --with-charset=utf8; make; make install
% echo "印刷用紙を複合機で印刷する。" | mecab
印刷用紙        名詞,一般,*,*,*,*,印刷用紙,*,*,ByTermExtractLen
を      助詞,格助詞,一般,*,*,*,を,ヲ,ヲ
複合機  名詞,一般,*,*,*,*,複合機,*,*,ByTermExtractLen
で      接続詞,*,*,*,*,*,で,デ,デ
印刷    名詞,サ変接続,*,*,*,*,印刷,インサツ,インサツ
する    動詞,自立,*,*,サ変・スル,基本形,する,スル,スル
。      記号,句点,*,*,*,*,。,。,。
EOS

こうすると、「印刷用紙」、「複合機」ともに優先して分割されるようになります。 ただし、この方法は、短い用語や一般的な用語が追加されないように注意した方がいいと思います。

Wikipediaでの用語抽出例

Wikipediaからオープンソースのカテゴリを持つページを抽出したテキストファイル6.4MBからTermExtractにより専門用語を抽出してみます。

なお、Wikipediaからのカテゴリを持つページの抽出は、以前、全文検索エンジンGroongaのRubyバインディングRroongaを使ったベンチマークプログラムで作成したデータベースから抽出しました。

% time cat example/open_source.txt | docker run -v /var/lib/termextract:/var/lib/termextract -a stdin -a stdout -a stderr -i naoa/termextract termextract_mecab.pl
real    0m57.540s
user    0m0.015s
sys     0m0.020s

解析結果の上位100位は以下の通りです。全データは、こちらから参照することができます。

% head -100 open_source_words.txt
オープンソース               3271565.53
ソースコード                  1148379.84
Linux                      1145244.41
Windows                              719143.07
フリーソフトウェア          528618.23
ファイルシステム             330097.36
プラグイン                      231639.42
Java                          224278.60
公式サイト                      178292.62
ソースファイル                119766.41
Linuxカーネル                    108254.88
ソフトウェア開発              99021.32
FreeBSD                       96416.05
Python                          85005.73
開発環境                          82837.95
BSDライセンス                    80794.42
設定ファイル                    79932.39
Webサイト                          76738.43
コンピュータシステム        71030.63
フレームワーク                 70935.05
Debian                       68897.67
コンピュータゲーム           68737.58
拡張機能                          66684.10
開発チーム                       64753.75
公式リリース                    62297.61
Unix系OS                             58288.22
Apache                           57019.52
Mozilla                          55182.90
処理系                             53580.87
Webシステム                       52866.46
Firefox                          50441.02
ファイル名                       49379.71
Webサーバ                          48128.29
管理画面                          46835.77
デスクトップ環境              46306.85
文字列                             44828.24
ゲーム機                          44209.68
Google                          44127.48
ファイル形式                    44066.47
開発プロジェクト              43722.48
仮想化                             42989.77
ゲームエンジン                 42329.06
ウェブブラウザ                 41486.02
Perl                          41174.69
Webアプリケーション           40369.26
フリーソフト                    40277.61
Debianプロジェクト              40133.80
Play                          39835.14
Apacheソフトウェア財団        39716.86
webページ                          36313.45
国際化                             35435.52
GNOME                           32105.18
コードベース                    30556.86
Webページ                          30230.03
GNUプロジェクト                 30071.87
文字コード                       29706.67
バックエンド                    27899.38
プロジェクト管理              27781.24
画面開発                          27641.52
著作権                             26789.01
ブラウザ                          26203.04
Unix                            25665.32
機能拡張                          25403.47
UNIX                          24603.10
デスクトップ                    24601.07
リンクコンピュータ           24400.02
サブプロジェクト              24241.51
Ruby                           24157.42
BSD系OS                              23188.30
アドベンチャーゲーム        23091.86
コマンドライン                 22857.34
作曲家                             22567.23
ファイルフォーマット        22391.98
変更点                             22186.33
Linuxシステム                     21900.20
ベースシステム                 21424.94
Unix系                        20711.56
ゲームプログラミング        20629.42
HTML                        20533.24
暗号化                             20299.04
編集機能                          19913.35
エンコード                       19837.66
オープンソース実装           19693.71
FLOSS                        19645.75
Windows用ゲーム                   19281.47
初期化                             19231.87
計算ソフト                       19102.70
クライアント                    19063.37
Emacs                          19013.35
研究プロジェクト              18959.65
開発終了                          18501.36
標準ソフト                       18411.54
オープンソース化              18354.86
MySQL                          18147.87
日本語化                          18143.13
Cライブラリ                      18091.82
ウェブサイト                    17744.98
機能開発                          17733.23
ブログ                             17712.72
データソース                    17667.48

経験則的に正規表現でフィルタをかけたおかげもありますが、重要度の上位はそこそこ良い感じにとれているのではないでしょうか。 なお、重要度が低い部分は結構ノイズがおおかったりするので、適宜閾値等を調整したり取捨選択したりする必要があると思います。

同様に、Wikipediaからファミリーコンピュータ用ソフトのカテゴリを持つテキストファイル11MBからTermExtractにより専門用語を抽出してみます。

%  time cat example/famicon.txt | docker run -
v /var/lib/termextract:/var/lib/termextract -a stdin -a stdout -a stderr -i naoa
/termextract termextract_mecab.pl > famicon_words.txt

real    1m1.901s
user    0m0.022s
sys     0m0.042s

解析結果の上位100位は以下の通りです。全データは、こちらから参照することができます。

# head -100 famicon_words.txt
ゲームオーバー                225391.74
コンピュータゲーム          207293.26
アクションゲーム             191859.12
ゲームソフト                   173559.54
アーケードゲーム              82471.63
攻撃力                             78720.54
ゲームシステム                 76020.80
シューティングゲーム        58060.15
バーチャルコンソール        47166.23
ゲーム画面                       47020.95
敵キャラクター                 41591.97
難易度                             38140.79
野球ゲーム                       33310.86
ゲームクリア                    31195.55
ステージクリア                 30310.27
ファミコンソフト              28704.64
アドベンチャーゲーム        27880.07
ゲーム作品                       25405.97
ゲーム機                          24178.18
ボスキャラクター              22827.36
ゲーム内容                       22718.59
ゲームモード                    22519.06
ボス戦                             19458.30
Aボタン                            19204.68
ボーナスステージ              18773.07
家庭用ゲーム機                 18195.87
プレイ                             16706.88
タイトル画面                    16570.34
残機                           14833.45
シリーズ作品                    14581.82
敵機                           14208.63
敵キャラ                          13983.64
戦闘機                             12714.64
Bボタン                            12165.97
ニンテンドーDS                  11585.81
ゲーム開始                       11576.77
ゲーム雑誌                       11135.99
パズルゲーム                    11131.51
ゲームシリーズ                 10931.45
ゲームボーイ                    10911.38
専用ソフト                       10823.23
キャラクターゲーム           10125.81
テレビゲーム                     9729.73
ゲームオリジナル               9713.91
ゲームブック                     8578.78
ボスキャラ                        8438.66
アクションゲーム画面         8421.34
敵弾                         8256.72
登場キャラクター               8193.54
攻撃アイテム                     8107.03
防御力                              7834.61
ゲーム終了                        7511.86
ファミリートレーナー         7510.19
ボス敵                              7395.66
攻略本                              7162.74
登場人物                           7125.86
戦闘力                              7112.11
仕事カード                        6867.87
ボスキャラクターボス         6849.71
攻撃ボタン                        6795.73
ゲームデザイン                  6549.28
ジャンプ力                        6441.60
ゲームデータ                     6272.59
パックマン                        6256.40
マリオシリーズ                  6251.48
守備力                              5980.39
ゲームソフトナムコ            5954.83
ファミコン用ソフト            5871.01
ゲームソフトサン電子         5733.77
移植作品                           5698.47
ゲームスタート                  5677.25
人同時プレイ                     5628.80
ナムコゲーム                     5594.78
体当たり                           5571.98
獣人                           5546.24
アクションステージ            5507.70
ハゲ丸                              5492.77
障害物                              5465.10
シリーズ作                        5406.64
ステージ構成                     5246.22
変更点                              5239.89
ステージ開始                     5236.79
スタートボタン                  5235.63
ゲームバランス                  5186.70
キャラクターデザイン         5149.77
ゲーム化                           5125.85
人対戦                              5061.89
赤影                            4954.96
対戦相手                           4934.96
PCゲーム                            4851.10
PCエンジン                         4830.22
ゲーム発売                        4825.91
ゲームソフトセガ               4792.47
マップ画面                        4769.02
リメイク                           4753.66
ボーナス点                        4691.56
攻撃方法                           4580.24
ステージボス                     4379.08
PC用ソフト                         4378.88
宝箱                             4226.46

「ゲームソフトセガ」、「ゲームソフトナムコ」、「ボスキャラクターボス」などあまり正しくない結合のされ方も含まれていますが、ある程度はそれらしい用語も抽出できていますね。 他のオプションを組み合わせたり学習情報によっては、うまく解析できるようになるかもしれません。

おわりに

このような一時的な解析環境の構築は一度やった後は、結構忘れがちなのでDockerで環境を作っておくと便利だなぁと思いました。

文書構造的に容易に抽出可能なタイトルやキーワードなどから固有名詞を抽出する方法が知られています。 たとえば、Wikipediaのタイトルやはてなキーワードなどがよく知られていますね。

よりキーワードを集めたい方は、TermExtractを使ったキーワード抽出を試してみるといいのではないのでしょうか。

最近は、word2vecなどに興味がある人が多いと思いますが、学習の前には用語を抽出して辞書に追加した方が面白い結果が得られると思いますよ。

word2vecや連想検索エンジンGETAssocのDockerファイルも近日中に作ろうと思っています。

7/14 記事を追加しました。

word2vecとプレーンテキストをフィルタや正規化をしつつ分かち書きしてくれるstring-splitterコマンドとベクトルを自由に足し引き演算(+-)できるようにしたword2vec-calcコマンドをDockerファイルdocker-word2vecで簡単に使えるようにしました。また、アナロジー以外のベクトル演算をした実験結果を紹介しています。

word2vecをDockerでプレーンテキストから簡単に使えるようにしました

全文検索エンジンGroongaユーザ勉強会@神戸を主催しました

2014/06/27(金)に全文検索エンジンGroongaユーザ勉強会@神戸を主催しました。

開催のきっかけ

草の根Groongaイベントのお誘いを受けて、関西圏でもGroongaのイベントがあるといいなと思い、神戸でも開催してみることにしました。

会議室の確保

人の集まり具合がどうなるかわからなかったので、三宮近辺でできるだけ費用が抑えられるというポイントで会場を探しました。WordBench神戸などが利用されているような貸会議室ビジネスしているところだと、平日夜間でも1万円を超えるところが多かったです。人が数十人来ることがほぼ確定しているプロダクトの勉強会なら千円徴収すればなんとかなりますが、小規模が想定される勉強会での利用は難しかったです。

そこで、公民館など市営の施設の会議室をこちらから探してみました。公民館等の場合、だいたい10数名規模の部屋で数千円といったところでした。

その他、インターネットで探して見ると、KIITOが1時間につき500円で時間単位の貸し出しOKで、且つ、比較的、予約も空いていたので利用することにしました。無料で備品も貸出しており、なかなか穴場なんじゃないかなぁと思いました。ただ、費用は安く抑えられましたが、駅からやや遠いのが難点でした。

告知

DoorkeeperやTwitter、メーリングリストなどで告知しました。また、近隣のRuby関西GDG神戸のAngularJSの勉強会などで簡単な開催のお知らせをしました。

当日の様子

19:00を超えると、入り口がclosedって札が立つのを知らなくて、入るのに戸惑った人がいて申し訳ありませんでした。

平日ということもあって、19:30ぐらいになるまでなかなか人が集まりませんでしたが、最終的には、当日キャンセルなしで合計10名が参加していただけました。ありがとうございました。

今回の勉強会では、Groongaの紹介と事例紹介を発表しました。

Groongaの紹介では、私が説明しながら、Groongaの開発に携わっている須藤(@ktou)さんが適宜、補足や質問に答える形で進めました。開発に携わっている方から直接、詳細な情報が聞けるいい機会になったんじゃないかなと思います。

事例紹介では、特許の全文検索サービスPatentFieldを紹介しました。当サービスでは、PHPからMroongaを使っていますが、Groongaの機能をすべて使いたかったので、全文検索はUDFを使ってGroongaのコマンドを使っています。基本的にGroongaのほぼすべての機能を使っているので、実際に使っている様子と工夫した点を紹介しました。

参加していただいた@shigeponさんが、ブログに勉強会の感想を書いてくれています。よければ、こちらもご参照ください。

懇親会

勉強会終了後、終電間近まで懇親会が行われました。懇親会では、Groonga関連の話もGroongaに関係ない話も盛り上がってた思います。@soundkitchenさんからdocker-mroongaについて紹介がありました。MroongaをDockerを使って簡単にイメージ作るにはこれしかない!と熱弁されていました。Dockerを使って、Mroongaを簡単にサーバにデプロイしたい方は是非使ってみるといいのではないでしょうか。

感想・反省点

進行がなかなかうまくいかず、発表を用意していただいた方もいらっしゃったのですが、時間を確保できなくて申し訳ありませんでした。

実際にコマンドをうちながら説明したいなぁと思ったのですが、現場では案外パッとでてこないので、事前に準備しておいたほうがよかったなぁとおもいました。

また、平日ということもあり、なかなか19時丁度に全員集まるのは難しかったので、今後、開催することがあれば、できるだけ休日に開催してみようかなと思っています。

勉強会の主催経験がなく拙い進行でしたが、参加いただいた皆様、および、わざわざ東京から来ていただいた須藤(@ktou)さん、どうもありがとうございました!

Groongaの今後への期待

当日できなかったGroongaの今後への期待の資料です。この資料は、メーリングリストで案内があった[groonga-dev,02439] Groongaの今後の開発への協力のお願いへの回答です。

61st Ruby/Rails勉強会@関西でLTしました

以下は、LTの資料です。

MacとRabbitの操作に戸惑ってしまい、デモの検証が一部しかできませんでした。デモができなかった分の検証結果を追記しています。

2014/6/27(金)19:00~神戸でGroongaの勉強会をします。Doorkeeperで募集していますので、興味がある方は是非ご参加ください。

http://koberoonga.doorkeeper.jp/events/11578

「Mroongaを使ったときの MySQLの制限との戦い」という内容で初LTしました

MySQL勉強会 in 大阪(第6回)でLTっていうのをはじめてやってみました。

内容は、「Mroongaを使ったときの MySQLの制限との戦い」です。

資料づくりにほとんど時間をかけられなくてすごい雑です。また、現場でちゃんとLTを見たこともなかったので、趣旨や作法があっているのかもよくわかりません。

うまくしゃべられなかった上に制限時間の5分を数十秒超えちゃってた気がします。

あまり人前での発表は得意ではないですが、無料で普段得られない経験値が得られるので大変お得だと思いました。

質問事項

LTの後、機材の調整の関係で少し時間があって、いくつか質問があったので覚えている範囲で書いておきます。

Q.ソースをいじってMroongaではいけるけど、その状態でInnoDBはどうなる?
A.ストレージエンジン側の制約をうけると思います。3072バイト制限はInnoDBでは3500バイトって書いてました。インデックス64個制限は、普段InnoDB使っていないのでわからないです。複数インデックス云々は、完全にGroongaのレイヤーで処理させる話なのでInnoDBには関係ないです。

Q.GroongaのコマンドはMySQLとは別にHTTPサーバたててる?
A.Groongaに直接コマンドを発行できるUDF(mroonga_command)があるのでそれを使っています。

Q.最終的にほぼGroongaでやるってことだけどMySQLを介す意味はある?
A.ないです。結局は、Groongaがはやいですよってことだけです。まぁでもやっぱりSQLで操作できるのはすごく楽で、GroongaでJSONをつくってloadさせるのは大変なんでINSERTやUPDATEはSQLでやっています。

国産の全文検索エンジンGroonga vs 世界的流行のElasticsearch

2014年4月21日は、第4回Elasticsearch勉強会ですね!

http://elasticsearch.doorkeeper.jp/events/8865

第4回Elasticsearch勉強会は、参加希望者が約200名の大反響なようです。

私は勉強会に参加できないので、C言語で書かれた国産の高速な全文検索エンジンGroongaと、Javaで書かれた世界的に勢いのあるElasticsearchについて性能の比較をしたいと思います。

  • 注意事項

今回の検証では1台あたりの馬力を比較するためにサーバ1台での全文検索性能について比較しています。

私は、Groonga(Mroonga)の利用暦が約2年であるのに対し、Elasticsearchの利用暦は2日です。このため、Elasticsearchに対するチューニングの不備や公平な比較になっていない点が含まれている可能性があります。

Elasticsearchでの言葉の扱いに慣れていないため、誤った語句を使っている可能性があります。

Groongaとは

GroongaはC言語で書かれた国産の高速な全文検索エンジンです。Groongaは、C言語から呼び出すことが可能な全文検索ライブラリとしての機能を有し、また、単体で全文検索サーバとしての機能も有します。  

Groongaでは、MySQLのストレージエンジンとしてSQLベースで容易に高速な全文検索が可能なMroongaが提供されています。GroongaやMroongaは、それ単体ではスケールしませんがfluentdのプラグインとして動作するDroongaSpiderストレージエンジンを使うことによりデータベースシャーディングが可能です。

Elasticsearchとは

Elasticsearchは、Javaで書かれた全文検索ライブラリApache Luceneを用いた全文検索、解析サーバです。Elasticsearchは、RESTfullで容易にアクセスすることができ、データを容易にスケールさせることができます。

また、Elasticsearchは、全文検索サーバSolrでも使われている歴史あるApache Luceneを使っていることもあり、非常に高度な全文検索機能、集計機能、豊富なプラグインを有し、多種多様な運用ツールとの連携の実績があります。

最近では、Elasticsearchとfluentdとkibanaを使ったログの可視化等が非常に流行っているようです。

検証データ

  • 日本語Wikipedia - Articles, templates, media/file descriptions, and primary meta-pages.

http://dumps.wikimedia.org/jawiki/20131119/ *1

XMLデータサイズ レコード数
7.3GiB 1,766,247

Wiki記法等は除去せずそのまま利用します。

7/19追加検証

http://dumps.wikimedia.org/jawiki/20140714/

検証環境

  • さくらのクラウド ×1台
CPU メモリ ディスク
4Core 16GB SSD 100GB

7/19追加検証

  • さくらの専用サーバ ×1台
CPU メモリ ディスク
Intel(R) Xeon(R) CPU E5620 @ 2.40GHz 1CPU 4Core 32GB HDD 2TB

Elasticsearchの検証手順

環境構築

CentOSにElasticsearchをインストールする方法の手順に沿って、Elasticsearch1.1.1をインストールします。 ヒープサイズを8GiBに設定し、JVM起動時にメモリを確保するように設定しています。 また、デフォルトのシャード数を1に設定しています。

% vi /etc/init.d/elasticsearch
ES_HEAP_SIZE=8g
MAX_OPEN_FILES=65535
MAX_LOCKED_MEMORY=unlimited
% vi config/elasticsearch.yml
http.port: 9200
index.number_of_shards: 1
bootstrap.mlockall: true

ElasticSearchの運用とか (2)を参考にさせていただきました。ありがとうございます。

スキーマ

以下のような簡潔なテーブル構造を作成することを想定します。

id(integer) title(string) text(string)
150813 スポーツのプロリーグ一覧 '''スポーツのプロリーグ一覧'''(スポーツの...
150815 Category:スポーツ競技大会 {{Pathnav|主要カテゴリ|文化|娯楽|スポーツ|...

上記のテーブル構造に相当するスキーマを作成します。 アナライザーは、Groongaに合わせるためにngram_tokenizerでmin_grammax_gramを2にしています*2。 なお、Elasticsearchでは文字の正規化やタグ除去、ストップワード除去等フィルタがかなり豊富に用意されていますが、今回は単純な全文検索性能を比較するため、それらを使用しません。

% vi mapping.json
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ngram_analyzer": {
          "tokenizer": "ngram_tokenizer"
        }
      },
      "tokenizer": {
        "ngram_tokenizer": {
          "type": "nGram",
          "min_gram": "2",
          "max_gram": "2",
          "token_chars": [
            "letter",
            "digit",
            "punctuation",
            "whitespace",
            "symbol"
          ]
        }
      }
    }
  },
  "mappings": {
    "text": {
      "properties": {
        "id": {
          "type": "integer"
        },
        "title": {
          "type": "string",
          "analyzer": "ngram_analyzer"
        },
        "text": {
          "type": "string",
          "analyzer": "ngram_analyzer"
        }
      }
    }
  }
}

スキーマファイルをPOSTします。

curl -XPOST localhost:9200/wikipedia -d @mapping.json

これにより、wikipediaという名前のindexのスキーマが設定されました。なお、Elasticsearchは、スキーマレスでも動作します。

7/19追加検証
最初の検証では、punctuationとwhitespaceが入っておらず、Groongaと転置索引のトークンの量に違いがありました。追加検証では、Groongaと合わせるためにpunctuationとwhitespaceを有効にしています。

更新手順

更新は、たとえば、以下のようなPUTアクセスで行います。

% curl -XPUT 'http://localhost:9200/wikipedia/text/1' -d '
 { "id": "1", "title": "title1", "text": "text1" }
'

Gistに上げたPHPスクリプトを用いて、WikipediaのXMLデータを1件ずつPUTで更新します。

Elasticsearchでは、バルクアクセスのAPIや各スクリプト言語のライブラリを用いることもできるようですが、今回は単純に1件ずつCURLPUTするだけにしました。

検索手順

検索は、たとえば、以下のようなGETアクセスで行います。titleフィールドとtextフィールドに対してsearchqueryを全文検索し、一致するidを0件出力します。ここでは、全文検索性能のみを比較するため、出力数は0にしています。

curl -XGET http://localhost:9200/wikipedia/text/_search -d'
{
  "from" : 0, "size" : 0,
  "fields": ["id"],
  "query":
    {
      "multi_match" : {
        "query":    "\"searchquery\"",
        "fields": [ "title", "text" ]
      }
    }
}'

7/19追加検証
以前の検証結果では、"でくくっていなかったため、OR検索となっていました。追加検証では、"でくくってフレーズ検索としています。Elasticsearchでは、空白が含まれていなくとも、"でくくらないと、アナライザーによって分割されたトークンがOR検索されます。たとえば、「東京都」は、「東京」OR「京都」で検索されます。

Wikipediaのカテゴリのうち5文字以上の日本語のみのカテゴリからランダムに1万件を抽出して全文検索します。

Gistに上げたPHPスクリプトを用いて、1万件のカテゴリを1件ずつGETで全文検索します。更新と同様に、単純にCURLGETするだけです。

なお、Elasticsearchでの名前体系や扱い方に慣れておらず、不平をつぶやいていたら、@johtaniさんがフィールドの指定方法やカウントの見方を教えてくれました。ありがとうございました。Elasticsearchについて無知なにも関わらず、色々不平をつぶやいて大変失礼しました。

GroongaやDroongaでの名前体系に慣れていると、Elasticsearchの名前体系に慣れるのがなかなか大変でストレスを感じます。たぶん、Elasticsearchに慣れている方がGroongaやDroongaを触ろうとしてもそう感じるんじゃないかなと思います。

Groongaの検証手順

環境構築

Groonga4.0.1とnginxベースのgroonga-httpdをインストールします。

% rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
% yum makecache
% yum install -y groonga
% yum install -y groonga-tokenizer-mecab
% yum install -y groonga-normalizer-mysql
% yum install groonga-httpd

スキーマ

上記と同様のテーブル構造に相当するテーブル定義を作成します。 トークナイザーはTokenBigramを設定し、ノーマライザーは設定していません。 こうすると、Groongaでは、一般的なバイグラムのルールに従ってテキストがトークナイズされます。

% vi table.ddl
table_create text TABLE_PAT_KEY UInt32
column_create text text COLUMN_SCALAR LongText
column_create text title COLUMN_SCALAR LongText
table_create text-text TABLE_PAT_KEY ShortText --default_tokenizer TokenBigram
column_create text-text index COLUMN_INDEX|WITH_SECTION|WITH_POSITION text title,text

Groongaのテーブルを作成します。

% groonga -n /var/lib/groonga/db/db < table.ddl
[[0,1397980056.85291,0.00288963317871094],true]
[[0,1397980056.85586,0.00232267379760742],true]
[[0,1397980056.8582,0.00235915184020996],true]
[[0,1397980056.86058,0.00229644775390625],true]
[[0,1397980056.86289,0.00667881965637207],true]

コマンドによってデータベースが新規作成された場合、groonga-httpdから操作できるようにファイルオーナーをgroonga:groongaに修正します。groonga-httpdが起動している場合、すでにgroonga:groongaでデータベースがつくられていると思います。

% chown groonga:groonga /var/lib/groonga/db/db*
% service groonga-httpd restart

これにより、textという名前のテーブルが作成されました。Groongaでは、MySQLなどと同様に明示的なテーブル定義を必要とします。

更新手順

更新は、たとえば、以下のようなPOSTアクセスで行います。

% curl -X POST 'http://localhost:10041/d/load?table=text' -d '
 [{"_key":1,"text":"text1","title":"title1"}]
'

Gistに上げたPHPスクリプトを用いて、WikipediaのXMLデータを1件ずつPOSTで更新します。

Groongaではデータのみを追加した後に全文インデックスを追加することにより最適化された静的インデックス構築ができますが、今回は単純にCURLで1件ずつPOSTするだけです。

なお、普段はGroongaをMySQLから利用できるMroongaを利用しており、GroongaのHTTPサーバに対してPOSTでうまく更新できないなぁとつぶやいていたら、@ktouさんがnginxベースのgroonga-httpdを使えばいいことを教えてくれました。ありがとうございました。

検索手順

検索は、たとえば、以下のようなGETアクセスで行います。titleカラムとtextカラムに対してsearchqueryを全文検索し0件出力します。ここでは、Elasticsearch同様、全文検索性能のみを比較するため、出力数は0にしています。また、Groongaでは、ヒット数が0件の場合、自動的に前方一致検索にエスカレーションするという機能があるためこれを抑制しています。

% curl 'http://localhost:10041/d/select?table=text&match_columns=title||text&query=searchquery&limit=0&match_escaltion_threshold=-1'

Wikipediaのカテゴリのうち5文字以上の日本語のみのカテゴリから上記と同じカテゴリ1万件を全文検索します。

Gistに上げたPHPスクリプトを用いて、1万件のカテゴリを1件ずつGETで全文検索します。更新と同様に、単純にCURLで1件ずつGETするだけです。

性能比較

更新時間

Elasticsearch Groonga
8853sec(2h27min) 21914sec(6h05min)

いつインデックスが更新されているかまでは追っていないので単純な比較はできないかもしれませんが、シーケンシャルなスクリプトの実行時間で比較すると、Groongaの方が2.5倍ほど遅かったです。

追記
Groongaの方はデータと転置索引の更新の両方が含まれた時間であり、Elasticsearchの方は転置索引の更新の時間は含まれていません。Elasticsearchは、リフレッシュ、フラッシュ、マージなどの転置索引の更新処理がデータの更新とは別に裏で走ります。

※トータルの更新時間には、XMLのパースが含まれています。

7/19追加検証

Elasticsearch Groonga
6689sec(1h51min) 20958sec(5h49min)

ディスク使用量

Elasticsearch Groonga
12.7GiB 18.9GiB

ディスク使用量は、Elasticsearchの方がコンパクトでGroongaの方が1.5倍ほど大きいですね。 Elasticsearchの方は設定をミスってしまって空白と所定の区切り文字が転置インデックスに入っていないですが、それを差し引いてもGroongaの方が大きいでしょう。

なお、Groongaの場合、インデックスのみを後で静的インデックス構築をすれば、ディスク使用効率が上がり検索性能がさらに向上します。なお、この方法はリアルタイム更新ではないのでここでは比較しません。

6/30追記
Groongaドキュメント読書会1で学んだ事のメモ - Qiitaを参考にすると、Groongaは、インデックスの即時更新のため、インデックス各データの間に隙間があり、データを間に差し込めるようになっているようです。このため、Elasticsearchに比べ、Groongaの方がディスク使用量が大きくなっているものと思われます。その分、インデックス更新にかかる処理コストが低いというメリットがあるようです。

http://groonga.org/ja/blog/2011/07/28/innodb-fts.html

7/19追加検証

Elasticsearch
(optimize前)
Groonga
19.3GiB 18.9GiB

punctuationとwhitespaceを有効にしたらElasticsearchの方が大きくなってしまいました。 おそらく、これはマージが終わっていないのでしょう。

以下のようにoptimizeをするとサイズが減少しました。

% curl -XPOST 'http://localhost:9200/wikipedia/_optimize'
Elasticsearch
(optimize後)
Groonga
16.5GiB 18.9GiB

検索時間

種別 Elasticsearch Groonga
トータル(1万件) 1050.737sec 424.797sec
平均 0.105sec 0.042sec
最長 0.792sec 0.368sec
最短 0.000992sec 0.000842sec

上記を比較すると、全文検索速度はGroongaの方が約2.5倍ほど速いことが判ります。 経験則から言うと、Groongaはこの数倍~10倍ぐらいのデータサイズであっても1台で十分に高速に全文検索できると思います*3

ただし、Groongaは、単体ではシャーディングすることができません。一方、Elasticsearchは、デフォルトのシャード数が5であることからもわかるように、複数台構成が前提となっており容易にシャーディングすることができます。

また、今回は単一アクセスの検索性能しか試していません。同時実行性能を含めるとどちらが勝っているかは判りません。

7/19追加検証
フレーズ検索でもGroongaの方がElasticsearch(optimize後)よりも約2.8倍ほど速いことが判ります。Elasticsearch(optimize前)であれば約4.3倍ほど速いことが判ります。ちなみにGroongaでは、リアルタイム更新をしても速度劣化はほとんどないため、optimizeという処理はありません。詳しくはこちら

種別 Elasticsearch
(optimize前)
Elasticsearch
(optimize後)
Groonga
トータル
(1千件)
216.161sec 141.701sec 50.062sec
平均 0.216sec 0.141sec 0.050sec
最長 4.313sec 1.037sec 0.339sec
最短 0.000960sec 0.00317sec 0.00215sec

おわりに

以上、サーバ1台、単一アクセスにおけるGroongaとElasticsearchの性能を比較しました。 まとめると以下のような比率になります。数値が高い方が性能が良いことを示しています。

性能種別 Elasticsearch Groonga
更新性能 2.5 1
ディスク使用効率 1.5 1
検索性能 1 2.5

7/19追加検証

性能種別 Elasticsearch
(optimize前)
Groonga
更新性能 3.13 1
ディスク使用効率 1 1.02
検索性能 1 4.31


性能種別 Elasticsearch
(optimize後)
Groonga
更新性能 3.13 1
ディスク使用効率 1.14 1
検索性能 1 2.83

上記の比較例では、更新性能、ディスク使用効率ではElasticsearchが勝っており、検索性能ではGroongaが勝っていました。なお、あくまで今回のテストケースによる結果であり、他のテストケースではどうかわかりません。

Elasticsearchは、今、世界的に勢いがあり、容易なスケール機能、豊富な機能、豊富なプラグイン、運用ツールとの連携等、様々なメリットがあります。 アナライザーやフィルターのラインナップは、歴史が長いApache Luceneのライブラリを使っていることもあり、現状、GroongaよりもElasticsearchの方が優れているでしょう。 MoreLikeThisや類似画像検索は、現在のGroongaにはない機能です。

現状、大規模なWebサービス等でサーバを何十台、何百台とたくさん並べて運用する場合は、Elasticsearchの方が利用しやすいかもしれません。

しかし、私は、サーバ1台あたりの全文検索自体の馬力ではGroongaの方が勝っていると考えています。また、弱点だったスケール機能は、2014年2月にDroongaがメジャーリリースされ解消されつつあります。 さらに、Groongaは、MySQLのストレージエンジンであるMroongaを利用することによりSQLベースで非常に容易に高速な全文検索をすることもできます。私はMroongaがあったので、データベースも全文検索の知識もまったくなかった状態からある程度Groongaが扱えるようになりました。

kuromojiトークナイザの検索モードやフィルタ機能程度の利点であれば、多少工夫すればGroongaやMroongaでも補えます。今、Mroongaを使っていて、高度な検索式や豊富な全文検索機能を追加したいと考えている方は、まずは、GroongaやDroongaを検討してもいいと思います。Mroongaをストレージモードで使っているならデータベースそのままでGroongaのコマンドが利用できますし、MySQLの制約からくるインデックスが使用できないことによる速度劣化であれば、Groongaのコマンドに置き換えるだけで10倍以上の検索速度になったりすると思います。詳しくはこちらを参照してください。

上記の比較はあくまで一例にすぎませんが、そこそこ大規模なデータベースに対して少ないサーバ台数で高速な全文検索を実現したいならば、私はGroongaがおすすめだと思っています。

私はGroonga(Mroonga)を使うことにより、データサイズが400GiB超のデータベースを専用サーバ1台でそこそこ実用的な全文検索速度を実現させることができました*4

データベースの規模や特性に応じて、ElasticsearchとGroongaを使い分けるのも良いかもしれません。

最近、Mroongaを使って全文検索Webサービスを作ったときにはまったことについて、いくつかブログ記事を書きました。GroongaやMroongaに興味があれば、こちらも参考になるかもしれません。

Mroongaを使って全文検索Webサービスを作ったときにはまったこと(第1回)
Mroongaのラッパーモードからストレージモードに変えた理由
数百GiBの全文検索用データベースをMroongaのストレージモードにしてはまったこと
Groongaがあまり得意でない類似文書検索に連想検索エンジンGETAssocを使った話

今後は、Groonga(Mroonga)を使って工夫した点等を書いていきたいと思っています。

7/22追記
GroongaとElasticsearchの転置索引の違いと更新反映速度の差、およびGroongaの静的索引構築とリアルタイム更新時の性能差について検証した記事を追加しました。よければ、こちらもご参照ください。
GroongaとElasticsearchにおける転置索引の違いと更新反映速度について

7/28追記
GroongaをKVSとして利用した場合のベンチマークについて記事を書きました。Groongaは単純なKVSとしてもかなり高速な性能を有しています。
GroongaとTokyoCabinetのHash表のベンチマークについて

9/9追記
ちなみに、Groongaの場合、トークナイザーをTrigramにし、さらに効率化した自作トークナイザ―を使うと検索速度が8倍ほど速くなります(平均 0.0063 sec)。

https://github.com/naoa/groonga-tokenizer-yangram

Groongaの自作トークナイザーの紹介 - Qiita

2015/3/9追記
最新のGroongaで以下のパッチを適用すると、さらに検索速度が1.5倍〜2倍ほど速くなります。

頻出トークンとレアトークンを一緒に検索したときの性能向上パッチ (groonga-dev,03095) - Groonga - fulltext search engine. (グルンガ) - SourceForge.JP

*1:データがやや古いのは、以前、Mroongaの性能をいろいろ検証したときと同じものを使ったためです。

*2:厳密にGroongaに合わせるためには、token_charsにwhitespaceとpunctuationも指定すべきでした。

*3:インデックスが適正に使われていることが前提です。Mroongaの場合、MySQLによる制約でインデックスが利かないケースが多々あります。

*4:アクセスが増えると参照分散させるために台数を増やす必要があると思います。実用的な速度かどうかは、アプリの要求次第によって変わると思います。デフォルトのトークナイザTokenBigramではこのサイズはさばけないと思います。自前でトークナイザを改修したり工夫しています。

ブログタイトルを変更しました。

旧タイトル:独学Webサービス開発ブログ
新タイトル:CreateField Blog

インターネット上には、たくさんの技術情報やソフトウェアを無償で提供されている方々がたくさんいます。
人から教えを請うていて、独学っていうのは独りよがりな感じがしたので辞めました。

数百GiBの全文検索用データベースをMroongaのストレージモードにしてはまったこと

前回は、全文検索Webサービスを作ったときにはまったことの第2回として、 Mroongaのラッパーモードからストレージモードに変えた理由という記事を書きました。

今回は、Mroongaのストレージモードにしたことによってはまったことについて書きたいと思います。

Spiderストレージエンジンを使ったMroongaの分散構成の検討

当初、データベースを複数に分割し、Spiderストレージエンジンを使ってデータベースシャーディングする予定でした。

Spiderストレージエンジンは、ストレージエンジンの種類を問わずデータベースを水平分散させることができるMySQL/Mariadbのストレージエンジンです。 Spiderストレージエンジンは、国産で個人の方が開発されたストレージエンジンでMariaDB10.0系にすでにバンドルされています。 Spiderストレージエンジンの開発者の方は、全文検索Mroongaストレージエンジンの開発にも携わられています。

Spiderストレージエンジンは、非常に簡単にデータベースシャーディングすることができ、既存のSQLをそのまま使うことができます。

前回説明したように、ドリルダウン検索*1が非常に便利でWebアプリの機能として組み込みたいと考え、Mroongaをラッパーモードからストレージモードに変更し、全文検索はGroongaのコマンドを使うことにしました。

しかし、SpiderストレージエンジンはSQLベースで分散するため、Groongaのデータベースに直接コマンドを発行することはできません。 当時のGroongaには、分散機能がありませんでした*2

そこで、約400GiBのデータベースを分散させずに良好なパフォーマンスが得られるかという無謀な挑戦がはじまります。

データベースの統合によるカラムサイズ制限

Groongaには、いくつかの制限事項が設けられています。

当時のドキュメントには記載がありませんでしたが、Groongaには1カラムに格納可能なデータサイズの上限値が設けられており上限値は256GiBです。

したがって、約400GiBのデータベースを1カラムに格納することができませんでした。

そこで、苦肉の策として1カラムを3カラムに分割させます。 テーブルには、年度を示すカラムがあったため、1999年以前、2000年~2009年、2010年以降の3つのカラムを作成し、 年度に応じてアプリケーション側で切り替えるようにしました*3

なお、次期GroongaであるGrnxxでは、上記の制限が撤廃できるように設計が検討されているようです。

https://docs.google.com/presentation/d/1R5YqedpDyI9NVNn6f_EkCBZ8miQAldrAxu5-AwjmPas/edit#slide=id.p

データベースの統合によるインデックス構築失敗再び

上記のようにカラムを分割することにより、カラムの上限による制限は回避することができました。

しかしながら、今度はまたインデックス構築に失敗するようになります。

第1回に書いたインデックス構築の失敗とは、また別の原因によるものです。

この事象は、データベースサイズが100GiBぐらいにならないと再現せず、簡単な再現セットを作るのが困難でした。

メーリングリストで相談すると、デバッグ手法を一から教えていただいたり、バックトレースログから推測されるバグの修正パッチなどきめ細やかな対応をしていただきました。

http://sourceforge.jp/projects/groonga/lists/archive/dev/2013-August/001718.html
http://sourceforge.jp/projects/groonga/lists/archive/dev/2013-August/001725.html

しかし、再現に半日かかることもありバックトレースログから原因をなかなか突き止めることができませんでした。

そうしていると、わざわざテストマシンを用意していただけることとなり、当方の100GiB以上の再現可能なデータベースを直接提供して解析していただけることになりました。

http://sourceforge.jp/projects/groonga/lists/archive/dev/2013-September/001739.html

これによりオーバーフローしている箇所を突き止め、バグを修正していただけました。こうして、数百GiBのデータベースでも正常にインデックス構築ができるようになりました。

http://sourceforge.jp/projects/groonga/lists/archive/dev/2013-October/001866.html

以上のようなきめ細やかな対応を全て無償で行っていただきました。

個別環境による検証等は、有償のサポートサービスを契約すべきなのかもしれません。無償にも関わらず、ここまできめ細やかなご対応どうもありがとうございました。

おわりに

以上のようにして、Mroongaのストレージモードで400GiB超のデータベースのインデックス構築ができるようになりました。

しかし、この後の検証によりデフォルトのトークナイザのTokenBigramでは、全文検索のパフォーマンスがあまり芳しくないことが判明します。サイズがでかすぎるので当然といえば当然です。

そこで、400GiB超のデータベースの全文検索のパフォーマンスをできるだけ改善できないかを試行錯誤することになります。

次回は、全文検索のパフォーマンスをできるだけ良くするために試行錯誤したことについて書こうと思っています。投稿まで少し時間が空くと思います。

6/26 記事を追加しました。
Groongaがあまり得意でない類似文書検索に連想検索エンジンGETAssocを使った話

2014-11-29(土)13:30 - 17:30
年に1度のGroongaに関するイベントがあります。Groongaを使っている人、興味がある人は参加してみてはいかがでしょうか。

全文検索エンジンGroongaを囲む夕べ5 - Groonga | Doorkeeper

*1:他の全文検索エンジンやDroongaではファセット検索と呼ばれています。

*2:2014年2月には、Droongaと呼ばれるGroongaの分散システムがメジャーリリースされています。

*3:非常に不格好なのでお勧めしません。