FAT47の底辺インフラ議事録

学んだことのメモ帳です

ついにメジャーリリースしたGroonga ストレージエンジンを試してみた

公開から約1年が経ち、ついに本日Groonga Storage Enginev1.0.0でメジャーリリースとなったので早速試してみました。
groongaストレージエンジン(mroonga)とは、全文検索エンジンgroongaをベースにしたMySQLストレージエンジンです。Toritonnプロジェクトの後継として開発されており、Toritonnと比べ以下のような特徴があります。
動的な組み込みが可能
ToritonnはMySQLソースコードを直接編集する必要があったため、自分でビルドするかToritonn配布バイナリを利用しなければいけませんでした。groongaはMySQL5.1から利用できるpluginタイプのストレージエンジンになっているので、動的にロードすることが可能です。
更新性能向上
ToritonnはMyISAMを利用していたため、更新が発生するとテーブルロックがかかる為更新性能に難がありました。

今回メジャーリリースによる改良点と修正点は以下の通りです。
http://mroonga.github.com/news.html

公式サイトより引用


改良

  • [ラッパーモード] drop index対応。 #1040
  • [ストレージモード] GEOMETRY対応。(ただし、カラムに保存できる型はPointのみ対応。インデックスを利用した位置検索はMBRContainsのみ対応。) #1041
  • [ストレージモード] マルチカラムインデックスに対応。 #455
  • [ストレージモード][ラッパーモード] 全文検索用パーサー(トークナイザー)のカスタマイズに対応。 #592
  • configureにデフォルトの全文検索用パーサーを指定する --with-default-parser オプションを追加。
  • 実行時にデフォルトの全文検索用パーサーを指定する groonga_default_parser 変数を追加。
  • [ラッパーモード] ストレージモードで実装している order と limit が指定された場合に必要のないレコードを返さないようにする高速化に対応。
  • [ストレージモード] 1つの select 中での複数の match against 指定に対応。
  • [非互換][ストレージモード] _score カラムの削除。代わりにMySQL標準の書き方である match against を使ってください。
  • [ラッパーモード] プライマリキーの更新に対応。
  • MySQL 5.5.16に対応。
  • CentOS 6に対応。
  • groonga 1.2.6に対応。(1.2.5以下のサポートを削除。)


修正

  • [Ubuntu] Lucid上でインストールエラーが発生する問題を修正。 (Isao Sugimotoさんが報告)
  • auto_incrementを使った場合にテキストデータが壊れる問題を修正。 (@zaubermaerchenさんが報告) #1072
  • [Ubuntu] Lucid上でテーブルを削除するとクラッシュする問題を修正。 #1063 (Isao Sugimotoさんが報告)
  • MySQLと同じビルドオプションを使っていなかった問題を修正。 GitHub#4 (groongaのGitHubのIssues) (Tomohiro MITSUMUNEさんが報告)

Groonga Storage Engineの二つの動作モード
groonga0.7から2つの動作モードどちらかを選んで利用できるようになりました。

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

ストレージモード
ストレージモードはデータストアも含めてgroongaを利用します。MyISAMInnoDBなど既存のストレージエンジンの代替として動作します。groongaコマンドで直接データベースを操作することもできます。

ラッパーモード
ラッパーモードは全文検索機能のみgroongaを利用し、データストアはInnoDBなどのストレージエンジンを利用します。
多くの利用実績があるInnoDBを利用できるので信頼性のあるデータベースとして利用できます。

実際にCentOS5.7でgroonga storage engineを利用するまでの手順を紹介します。
必要なもの

  • MeCab
  • MeCab-IPA辞書
  • MySQL5.5
  • groonga
  • groonga storage engine(mroonga)

MeCabのインストール
形態素トークナイズした全文検索を利用するので、先にMeCabをインストールしておきます。

IPA辞書のインストール
MeCabには辞書が含まれていないので推奨されているIPA辞書を入れます。

MySQLのインストール
MySQL5.5の最新版のソースコードを使ってインストールします。
下記のエントリーを参考にしてインストールしてください。

CentOS5.7にMySQL5.5をソースからインストール

groongaのインストール
groongaストレージエンジンであるmroongaを利用するにはgroonga本体が必要であるため先にインストールします。

groongaストレージエンジン(mroonga)のビルド
以下のサイトからmroongaのtarをダウンロードしてきます。
https://github.com/mroonga/mroonga/downloads


tar zxvf groonga-storage-engine-0.9.tar.gz
cd groonga-storage-engine-0.9


./configure PKG_CONFIG_PATH=/usr/lib/pkgconfig --with-mysql-source=/home/src/mysql-5.5.16 --with-mysql-config=/usr/local/mysql/bin/mysql_config
make
make install

インストール完了すると、下記のメッセージが表示されます。
MySQLプラグインディレクトリである/usr/local/mysql/lib/pluginにha_groonga.soが配置されています。

----------------------------------------------------------------------
Libraries have been installed in:
   /usr/local/mysql/lib/plugin

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
----------------------------------------------------------------------

MySQLプラグインを読み込みます。


mysql> INSTALL PLUGIN groonga SONAME 'ha_groonga.so';

が、エラーが表示されました。

ERROR 1126 (HY000): Can't open shared library '/usr/local/mysql-5.5.16/lib/plugin/ha_groonga.so' (errno: 13 libgroonga.so.0: cannot open shared object file: No such file or directory)

mroongaインストール後にldconfigコマンドが必要だったようです。


ldconfig

mysql> INSTALL PLUGIN groonga SONAME 'ha_groonga.so';
Query OK, 0 rows affected (0.49 sec)

成功しました。


mysql> SHOW ENGINES;

+--------------------+---------+------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                    | Transactions | XA   | Savepoints |
+--------------------+---------+------------------------------------------------------------+--------------+------+------------+
| MyISAM             | YES     | MyISAM storage engine                                      | NO           | NO   | NO         |
| PERFORMANCE_SCHEMA | YES     | Performance Schema                                         | NO           | NO   | NO         |
| CSV                | YES     | CSV storage engine                                         | NO           | NO   | NO         |
| MRG_MYISAM         | YES     | Collection of identical MyISAM tables                      | NO           | NO   | NO         |
| InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES          | YES  | YES        |
| MEMORY             | YES     | Hash based, stored in memory, useful for temporary tables  | NO           | NO   | NO         |
| groonga            | YES     | Fulltext search, column base                               | NO           | NO   | NO         |
+--------------------+---------+------------------------------------------------------------+--------------+------+------------+
7 rows in set (0.00 sec)

ユーザ定義関数(UDF)のインストール
INSERTを行った時にgroongaから割当てられるレコードIDを取得するlast_insert_grn_id関数をインストールします。


mysql> CREATE FUNCTION last_insert_grn_id RETURNS INTEGER soname 'ha_groonga.so';
Query OK, 0 rows affected (0.07 sec)

ストレージモードで動作確認


mysql> CREATE DATABASE search;
mysql> use search;
mysql>
CREATE TABLE t1 (
c1 INT PRIMARY KEY,
c2 VARCHAR(255),
FULLTEXT INDEX (c2)
) ENGINE = groonga DEFAULT CHARSET utf8;
Query OK, 0 rows affected (1.24 sec)

mysql> INSERT INTO t1 VALUES(1, "これはリンゴです");
Query OK, 1 row affected (0.86 sec)

mysql> INSERT INTO t1 VALUES(2, "これはバナナです");
Query OK, 1 row affected (0.03 sec)

mysql> INSERT INTO t1 VALUES(3, "リンゴは赤いです");
Query OK, 1 row affected (0.05 sec)

mysql> SELECT * FROM t1 WHERE MATCH(c2) AGAINST("リンゴ");

+----+--------------------------+
| c1 | c2                       |
+----+--------------------------+
|  1 | これはリンゴです         |
|  3 | リンゴは赤いです         |
+----+--------------------------+
2 rows in set (0.00 sec)

どれだけの負荷に耐えられるのかはわかりませんが、Webサービスに欠かせないMySQLでの全文検索が非常に扱いやすくなるはずです。ぜひこの機会に試してみましょう。


参考リンク
http://groonga.org
http://mroonga.github.com/index.html