
「勉強会に行ってみた!」
第23回「MySQLとPostgreSQLと日本語全文検索」
2016.03.24
今回は日本語の全文検索の勉強会です。全文検索というとふつうはそれ専用のソフトウェアを使ってやるものですが、MySQLやPostgreSQLで直に検索しちゃうことだってできるよね?というすごい具体的な狙いが面白いなと思って、行ってきました。
(三土たつお)
■会場はDMM.com でした
会場は、駅から遠いことで有名な恵比寿のガーデンプレイスでした。ガーデンプレイスタワーにオフィスがあるDMM.comラボが会場を提供していたのでした。
おしゃれ!
DMM.comといえば、安定した本業の収入をもとに、このところ英会話やオンラインゲームなどいろいろな事業を展開していることで有名ですね。DMM.comラボはそれらの事業に必要な技術を研究開発する子会社なんだそうです。
DMM.comラボ技術広報の星野さん
という話をDMM.comラボの星野さんがいろいろとお話していました。
■主催者はクリアコードの須藤さん
須藤さん
勉強会の主催は株式会社クリアコードの須藤さんでした。「リーダブルコード」という本の解説の文章などで一方的に知っていたので、お会いできてとても嬉しかったです。
須藤さんは最初にこの勉強会の説明をした後、この時点で質問の募集を始めていました。発表が終わって「何か質問は?」となったときに誰も手を挙げず「シーン」となることがありますよね。それを防ぐために、質問はTwitterのハッシュタグ #mypgft でいつでも書いておいてね、というやり方でした。いいですね!
■MySQL の日本語全文検索について
まずはMySQLでの全文検索について、日本オラクルの山﨑さんのお話がありました。
山﨑さん
MySQLはバージョン4.0から全文検索に対応したんだそうです。でもその時点では対象はMyISAMだけでした。InnoDBに対応したのは5.6のときですが、日本語には対応していませんでした。そして5.7ではついに日本語を含む中国語、韓国語などの全文検索にも対応しました!
5.7からは字句解析方法としてN-gramとMeCabにも対応するようになりました。N-gram は最初から組み込まれていて、MeCabはパーサープラグインをインストールするが必要ありますが、バイナリに含まれているので設定で有効にするだけでOKとのこと。
ということで、実際にデモを見せてくれました。
サンプルのテーブルはこんな感じです。ここからまず単純に「ディスク」という言葉を含む行を検索したければ、こうします。
SELECT * FROM mecab.articles
WHERE MATCH(description) AGAINST ('ディスク' IN BOOLEAN MODE);
mecab.articleは対象のテーブル、descriptionは対象のカラム名です。二つのキーワードによるOR検索がしたければ、こう。
SELECT * FROM mecab.articles
WHERE MATCH(description) AGAINST ('バックアップ ディスク' IN BOOLEAN MODE);
これで、「バックアップ」または「ディスク」のどちらかを含む行が検索されます。
AND検索はこうです。
SELECT * FROM mecab.articles
WHERE MATCH(description) AGAINST ('+ディスク +トレンド' IN BOOLEAN MODE);
キーワードのそれぞれに + をつけます。あとで須藤さんが言っていたんですが、このORとANDの書き方って、ぼくたちが検索エンジンに入力するときのやり方とちょっと違いますよね。キーワードを二つ並べたらAND検索になるのに慣れているのではないでしょうか。
NOT検索は ? をつけます。
SELECT * FROM mecab.articles
WHERE MATCH(description) AGAINST ('+ディスク -トレンド' IN BOOLEAN MODE);
これで、「ディスク」を含むけど「トレンド」を含まない行だけが検索されます。いろいろできますよね。検索結果の順位の重み付けもできるそうで、なんかもう十分便利です! はやくMySQL5.7を使いたくなりました。
今後の予定としては、パフォーマンスの改善や、あいまい検索の対応などを進めていくとのことでした。その上で、ぜひMySQL の日本語全文検索を使って、感想や要望などをフィードバックしてほしいということでした。
■postgresql で全文検索
次は PostgreSQLでの全文検索について、NTTデータの澤田さんのお話です。
澤田さん
澤田さんは、PostgreSQL で全文検索をするpg_bigmというモジュールや、PostgreSQLそのものを作っていたりするそうです。すごい。
PostgreSQLには全文検索をするためのモジュールがいっぱいあります!
PostgreSQLでの全文検索モジュール
それらはこんなふうに分類できるそうです。日本語のパーサーとしてN-gramを使うもの、形態素解析できるもの、両方できるもの。
N-gramには、漏れがないメリットがあり、形態素解析にはノイズが少なかったり、意味を拾ってくれるメリットがあります。たとえば、「京都」で「東京都庁」がヒットしないみたいな。
澤田さんが pg_bigm を作ったのは、PostgreSQLでの全文検索になかなか決定版がなかったからだそうです。
定番としてはtextsearch_sennaがありますが、REINDEXが必要とか、すでにメンテナンスしていないなどの問題があります。それから、pg_trgm はインデックスをPGの中に持つ良さがあるんですが、日本語に未対応だったり、1、2文字の検索が低速というデメリットがありました。
pg_bigm はそういう問題を解決したというわけなんですね。
ちなみに、PostgreSQLのバージョンは9.4以降がおすすめだそうです。GINインデックスの圧縮機能というものが入ったのでインデックスが小さくなり、検索のスピードも上がりました。検索ロジックが賢くなって、検索文字数が長いほど顕著に早くなったんだそうです。写真の表を見ると9.3よりも数倍も早くなっているケースもありますね。
■須藤さん
ふたたび須藤さん
次はふたたび須藤さんです。須藤さんは、Mroonga と PGroonga というものを作っています。これは何かというと、国産の全文検索エンジンのGroongaをMySQLとPostgreSQLから使えるようにするツールです。具体的には、たとえばMySQLならストレージエンジンとして実装されています。
ここから、須藤さんのすごいベンチマークの話がはじまりました。「人のベンチマークはあくまで参考程度にとどめること!実際の環境でベンチマークを取ってみるまで信用してはいけません」と断った上でみせてくれたのは、まず検索の速さの比較でした。
データセットは、Wikipedia日本語版の約185万件、7GBです。メモリーは4GB、SSDが250GBという条件。写真のようなキーワードで検索してみたところ、MySQLが3分、PostgreSQLが4秒のところ、Mroongaは0.1秒になりました。
すごい速い!
というかMySQLが若干遅いような・・? でも、初めの注意のように、これを一般化してはいけないのです。データセットや環境、ベンチ方法によって結果はまったく変わってきますから。
それから、データ投入後に一括で検索用インデックスを作った場合の時間比較です。ここでもMroongaとPGroongaがむちゃくちゃ速い!
そして、使い勝手はなるべく元のDBのものになじむようにしたそうです。たとえばMySQLなら、テーブルを作る際に ENGINE=Mroonga としたうえで、MySQLのふつうの全文検索と同じ構文で検索できるようになっています。
さらに、使い勝手を独自に向上させている部分もあります。たとえばAND検索とOR検索。
MySQLの全文検索では、さっきもみたようにデフォルトがOR検索になっています。でも検索エンジンに慣れた一般ユーザーにとっては、デフォルトがAND検索のほうが分かりやすいだろうということで、そのようにしているんだそうです。
MySQLとPostgreSQLで直接検索するより絶対便利でしょ!といわんばかりの発表で、実際ものすごく使いたくなりました。
■事例紹介
最後はDMM.com ラボでの事例紹介ということで、DMM.comラボの板谷さんがお話をしてくれました。
DMM.comの運営するオンラインゲームには、コミュニティというものがあります。そうするとそこにはコミュニティの名前とか説明文、それからユーザー同士が会話をするトピック、スレッドといった文章が大量に生まれます。
それをMroonga で検索しているそうです。具体的にはMySQL5.1とMroonga2の組み合わせで2013年から運用してきて、速度面を含めて特に問題がないそうです。なんと!ここでもMroongaすごい!の流れですね。
でも、MySQL5.7の全文検索も試してみたいなとのことでした。
■質疑応答
さて、最後は質疑応答です。須藤さんの事前の準備のおかげで、いろいろと質問がすでに溜まっていたようです。この方式やっぱりいいですね。
たとえば、「MeCabよりN-gramのほうが遅いんでしょうか?」のような質問がありました。それに対しては「N-gramはインデックスのサイズがMeCabより大きくなることもあり、遅くなりがち」というような回答がありました。
■まとめ
MySQLとPostgreSQLを使った全文検索の話を聞きに行ったら、すっかりGroongaの速さや須藤さんプロダクトの使いやすそうな感じにやられてしまいました。でもMySQLユーザーなので、5.7はまず個人的に使ってみようと思いました。だって十分便利そうなんですから。
今回行った勉強会:「 MySQLとPostgreSQLと日本語全文検索 」
https://groonga.doorkeeper.jp/events/35295
ライターとしてはニフティのデイリーポータルZとかで書いてます。
http://mitsuchi.net/