隔週連載groonga

第3回すべてのMySQLユーザに高速な全文検索機能を! - mroongaの紹介

前回の地価マップでの事例紹介では、Ruby on Railsからgroongaとmroongaを使って位置情報検索をした事例を紹介しました。Active Recordを拡張して位置情報検索をするためのgemとその使い方も紹介していたので、Ruby on Railsユーザにとって実用的な内容だったのではないでしょうか。

今回は、前回使い方を紹介したmroongaについて、さらに紹介します。前回はmroongaの使い方がでてきましたが、今回は使い方の紹介はしません。その代わり、mroonga自身のことについて紹介します。mroongaの歴史、大事にしていること、さらにどのようなアーキテクチャになっているかについて説明します。

自分のアプリケーションで利用するプロダクトを検討するときに、プロダクトがどのような方向で作られているかを考慮していますか? 自分のアプリケーションが大事にしたいことをそのプロダクトでも大事にしているなら、相性がよいかもしれません。さて、mroongaはあなたが大事にしたいことを大事にしているでしょうか。

mroongaとは

mroongaはすべてのMySQLユーザに高速な全文検索機能を提供するオープンソースソフトウェアです。MySQLで全文検索をしたいなら一番最初に検討するべきプロダクトです。実際に多くのサービスでmroongaが動いています。例えば、前回の事例紹介にあった 地価マップ もそうですし、nanapiでも使っています[1]⁠。mroongaの採用事例はmroongaのサイトでも紹介しています。

MySQLには標準で全文検索機能が搭載されていますが、残念ながら日本語には対応していません。そこでmroongaの出番です。mroongaを使うことにより、MySQLに日本語対応の高速な全文検索機能を追加できます。

どうしてmroongaは日本語対応の高速な全文検索機能を追加できるのかというと、groongaを使っているからです。では、groongaをどのように使っているかというと…、それはもう少し後で説明します。その前に別の大事なことを説明しないといけません。

mroongaの読み方

大事なこととは「mroonga」の読み方です。読み方を知らないと他の人に紹介もできませんからね。⁠mroonga」「むるんが」と読みます。名前の由来は「MySQL」「groonga」です。⁠MySQL」「M」「groonga」「roonga」を組み合わせて「mroonga」です。

groongaを使ったミドルウェアやライブラリは「○roonga」という名前を使うことがあります。例えば、⁠rroonga」「nroonga」などがあります。これらはすべて「○るんが」と読みます。もちろん、⁠○roonga」となっていないミドルウェア・ライブラリもいろいろあります。興味のある人はgroongaのサイトの関連プロジェクトページを参照してください。

mroongaの歴史

groongaの前身がSennaだったということは第1回で紹介しました。実は、mroongaにも前身のプロダクトがあります。それがTritonnです。ちなみに、Tritonnの名前の由来は「晴海トリトンスクエア」です。開発者の池田さんがトリトンスクエアの近くで働いていたことが影響しています。⁠晴海トリトンスクエア」「トリトン」のスペルは「triton」で最後の「n」が1個なのに、どうして「Tritonn」は最後の「n」が2個なのか気になった人が少しはいるのではないでしょうか。これは違うスペルにすることでWebで検索しやすくするためです。groongaの名前付けと同じ理由ですね。

Tritonnもmroongaと同じくMySQLに日本語対応の高速な全文検索機能を追加するプロダクトでした。では、Tritonnとmroongaではどこが違うのでしょうか? 違いはいろいろあります。例えば、Tritonnはgroongaの前身のSennaを全文検索エンジンとして使用していて、mroongaはgroongaを全文検索エンジンとして使用しています。中でも一番の違いは、mroongaのほうがよりgroonga(Senna)という全文検索エンジンの性能を引き出すようなアーキテクチャになっているという点です。

Tritonnでの壁

第1回で紹介した通り、groongaは情報の鮮度を大事にしている全文検索エンジンです。新しい情報をすぐに検索できるようにする、更新しているからといって検索性能を落とさない、そういったことを実現するための設計になっています。これはgroongaがSennaの頃から大事にしてきたことです。そのため、もちろんTritonnでもこれを実現しようとしました。しかし、アーキテクチャの制限から壁にぶつかりました。それはMyISAMのロックです。

MyISAMとはMySQL 5.1までのデフォルトストレージエンジンです。ストレージエンジンとはMySQLの中でデータの読み書きや検索を担当するモジュールです。ストレージエンジンについては後でまた触れます。

TritonnはMyISAMを変更してSennaを組み込んでいたため、MyISAMの挙動の影響を大きく受けます。特に影響が大きかったのがロック周りです。前述の通り、Sennaは更新中でも検索ができるようなアーキテクチャになっていますが、MyISAMは検索と更新を同時に実行できないアーキテクチャでした[2]⁠。よってMyISAMへの検索と更新のリクエストが重なると、処理の前にロックを獲得して順番に処理を実行します。Sennaは同時に実行できるのにです。このため、TritonnのアーキテクチャではSennaの性能を活かしきれなかったのです。

Tritonnのアーキテクチャ
Tritonnのアーキテクチャ。MyISAMが更新時にロックするため、更新中に検索できない。

mroongaのアプローチ

Tritonnでぶつかった壁を超えるべく、Sennaはgroongaに進化します。TritonnがMyISAMを変更してSennaを組み込むというアプローチをとったのは、Sennaは全文検索機能のみを提供し、データストア機能を提供していなかったためです。データストアはMyISAMの機能を利用し、全文検索機能を追加しようというアプローチです。

Tritonnでの経験から、データストアを別のプロダクトに任せることにするとSennaの性能を活かしきれないケースがあることがわかりました。別のプロダクトの制約を受けるためです。その問題を解決するため、Sennaにデータストア機能をつけたものがgroongaです。この過程でAPIに互換性がなくなったため、Sennaからgroongaに改名したのです。

mroongaはSennaではなくgroongaを使うようにしました。groongaにはカラム指向のデータストアがあるため、MyISAMに依存する必要はなくなりました。完全にひとり立ちしたストレージエンジンとなったのです。

mroongaのアーキテクチャ
mroongaのアーキテクチャ。MyISAMとは独立し、更新時も検索できるようになった。

mroongaに改名した理由

mroongaもgroongaと同じくプロダクト名を変えています。改名の理由はgroongaと同じで互換性がなくなるからです。

後述しますが、mroongaはMySQL 5.1から使えるようになったプラガブルストレージエンジンという仕組みを使っているため、MySQL 5.1以降のみサポートしています[3]⁠。一方、TritonnはMySQL 5.0のみサポートしていました。異なる仕組みを使っているため使い方が少し変わり、完全に互換とはいかなくなります。

また、全文検索エンジンとして、TritonnはSennaを使っていて、mroongaはgroongaを使っているという違いもあります。Sennaとgroongaではデータベースのファイルフォーマットが違うため、移行する際にはデータベースをダンプ・リストアする必要があります。

このように、互換性がなくなるためプロダクト名を変えることになりました。とはいえ、一番大きい理由は、Sennaも名前を変えたからTritonnも名前を変えよう!だったかもしれません[4]⁠。

ただ、Sennaをgroongaに改名したときと同じように、Tritonnからmroongaに改名したことでアップデートの心理的な敷居をより高くしてしまいました。最近ではTritonnからmroongaに乗り換えたという声をみかけるようになりましたが、mroongaをリリースした当時はなかなかアップデートしてもらえませんでした。そのため、groongaと同じように、今後はmroongaも改名しないでしょう。

これがmroongaの歴史です。どんな歴史をたどってきたか、イメージがつかめたでしょうか。

mroongaの特長

mroongaはgroongaのよいところをMySQLから利用できることが特長です。具体的には、次の長所をMySQLから利用できます。

  • 更新内容をすぐに検索可能に!
  • 更新中に検索性能を落とさない!
  • 高速な位置情報検索!
  • 日本語対応!

mroongaはgroongaとの親和性を高めることだけに注力しているわけではありません。MySQLとの親和性を高めることにも注力しています。MySQLとの親和性を高めることにより、MySQLが提供している有用な機能をmroongaでも使うことができます。例えば、MySQLが提供しているレプリケーション機能をmroongaでも使うことができます。groonga単体ではレプリケーション機能を提供していません[5]が、mroongaではMySQLが提供する機能を使って実現できます。

2013年5月現在では、⁠インストールしたら、後は普通のMySQLとして使える」日本語に対応した全文検索システムはmroongaだけです。MySQLでmroongaを使わずに日本語に対応した全文検索をする場合、次の2つの選択肢があります。

  • アプリケーション側でデータを前処理してMySQL組み込みのMyISAMやInnoDBの全文検索機能を利用する[6]⁠。
  • SolrやSphinxなどMySQLとは別の全文検索システムと連携する。

アプリケーションから見ると、どちらの場合もひと手間増えます。ひと手間の大きさはまちまちです。ひと手間をしてくれるライブラリが提供されるケースもあるため、その場合はひと手間は小さくなりますが、提供されていない場合は結構なひと手間になることもあります。

システム管理者から見ると、MySQLに加えて別の全文検索システムも管理する必要があります。そのため、運用のコストは大きくなります。

mroongaはMySQLとキレイに統合されているため、これまで通りの開発・運用ノウハウを活かしながら高性能の日本語対応全文検索システムを実現できます。

mroongaのアーキテクチャ

mroongaはMySQL 5.1から導入されたプラガブルストレージエンジンという仕組みを使っています。前述の通り、ストレージエンジンとはMySQLの中でデータの読み書きや検索を担当するモジュールです。MySQL 5.0まではMySQLをビルドするときに一緒にストレージエンジンもビルドしないといけませんでした。MySQL 5.1からは、ストレージエンジンを別途ビルドして動いているMySQLに動的に組み込めるようになりました。これがプラガブルストレージエンジンという仕組みです。

プラガブルストレージエンジンを利用したMySQLアーキテクチャ
下の方にある「プラガブルストレージエンジン」という部分が、プラガブルストレージエンジンのレイヤー。SQLを解析してどのように処理をするかはプラガブルストレージエンジンより上のレイヤーが実行する。ストレージエンジンはデータの保存や範囲検索など具体的な読み書き・検索を受け持つ。「プラガブル」の名の通り、後から動的に追加できる。http://dev.mysql.com/doc/refman/5.1/ja/pluggable-storage-overview.htmlにより詳細な図がある。

mroongaには次の2つの動作モードがあります。

  • ストレージモード
  • ラッパーモード

ラッパーモードはプラガブルストレージエンジンという仕組みをうまく使った動作モードです。それぞれ順に説明します。

ストレージモード

ストレージモードはgroongaのよさをそのまま活かすための動作モードです。groongaをライブラリとして使用し、groongaのデータベースに対してデータの読み書き・検索を行います。もちろん、検索性能を落とさずに更新できるというgroongaのよさをきちんと発揮できます。

ストレージモード
すべての処理をmroongaが行い、groongaとの架け橋となる。

groongaとの密な連携

ストレージモードではすべてのデータをgroongaのデータベースに保存しているため、mroongaで書き込んだデータをgroongaで検索することができます。せっかく今まで通りSQLでアクセスできて便利なのに、groongaで検索したいことってあるの?と思いますよね。場合によってはあります。例えば、第1回で紹介したドリルダウン機能を使う時です。ドリルダウン機能はSQLでは効率よく実現できないため、groongaで直接検索したくなるケースの1つです。

そんなgroongaで直接検索したくなるケースのために、mroonga経由でgroongaのコマンドを直接実行できる機能を用意しています。それがmroonga_command()ユーザー定義関数です。mroonga_command()を使うとgroongaのコマンドを実行してその結果をJSONとして受け取れます。SQLの世界とはなじんでいませんが、別途groongaサーバーを立ちあげるよりは楽だろうということで用意しました。

SQLですべての操作を実現できないのであれば、他の全文検索エンジンとの組み合わせでもいいのでは?と思いますよね。もちろん、それも選択肢の1つです。アプリケーションが普通のSQL以外の方法で検索を実行しないといけないのはmroonga_command()を使う場合も他の全文検索エンジンと連携する場合も同じですが、mroonga_command()を使う場合は管理サービスが増えないという違いがあります。どのような構成にするのが自分たちにあっているか、開発と運用の両方を考慮して検討してみてください。

制限

ただし、groongaがトランザクションをサポートしていないため、ストレージモードではトランザクションを使えません。トランザクションを使いたい場合は次の2つの方法があります。

  • 後述するラッパーモードを使う。
  • InnoDB[7]をマスターにし、スレーブをmroongaにしたレプリケーションをする。

ラッパーモードは次項で説明しますので、ここではスレーブをmroongaにする方法について簡単に補足します。

スレーブ側にはマスター側でコミットされたデータだけが送られてくるため、マスター側にだけトランザクションがあれば十分です。更新をマスター側で行い、検索をスレーブ側で行うことにより、トランザクションを使いながらmroongaの日本語対応の高速な全文検索機能を使うことができます。

ラッパーモード

ラッパーモードは他のストレージエンジンに全文検索機能と位置情報検索機能を追加するための動作モードです。Tritonnでやっていたように、データストアに別のストレージエンジンを、全文検索と位置情報検索だけにgroongaを使うことになります。

ただし、Tritonnと違って既存のストレージエンジンを変更して組み込むということはしていません。そうではなく、ラッパーモードの名前の通り、既存のストレージエンジンをラップすることで実現しています。これは、プラガブルストレージエンジンという仕組みによりストレージエンジンのモジュール化が進んだためできるようになったことです。

ラッパーモード
全文検索と位置情報検索のみmroongaが行い、残りはラップしているストレージエンジンに任せる。

ラッパーモードを使うことにより、既存のストレージエンジンのよいところを使いながら、全文検索機能だけをgroongaに任せることができます。いいとこどりですね。

まとめ

mroongaの歴史と大事にしていること、そして、大事にしていることを実現するためにどのようなアーキテクチャになっているかを紹介しました。mroongaのサイトにチュートリアルがあるので、試してみたくなった人はぜひそちらを読んでみてください。

mroongaのサイトに触れたついでに、最後にmroongaのサイトのURLの最新情報を紹介します。2013年4月中旬頃からmroonga用のドメインmroonga.orgを取得し、公式URLはhttp://mroonga.org/になりました。これまでは、mroonga.github.comだったのですが、2013年4月上旬にmroonga.github.ioにURLが変わりました。URLが変わってしまうならいっそ独自ドメインへ!ということで独自ドメインでの運用を開始しました。

次回は事例紹介です。Rubyで作られている行指向のソースコード検索エンジンMilkodeの事例です。Rubyからgroongaをライブラリとして使っています。楽しみですね。

おすすめ記事

記事・ニュース一覧