もはやレガシーとなったMySQL 5.0という縛りがなくなることで、MySQL 5.1以降の先進的な機能を取り入れることができます。特にMySQL 5.6ではその進化が甚だしく、次の点を始めとする新機能が利用できます。
CPUスケーラビリティの向上
サブクエリを始めとするオプティマイザの最適化
GTIDを利用したフェイルオーバー
memcached API対応
より詳細な情報は次の記事を参照ください。
参照ロックフリー
ストレージモードでは、groongaの性能特性をフルに活かした高速なデータ更新・全文検索・位置情報検索が可能となります。
ストレージエンジンにInnoDBを利用できること
mroongaのラッパーモードを利用すれば、全文検索機能に関してはmroongaが担い、それ以外を別のストレージエンジンに委ねることもできます。これはつまり、歴史が長く信頼性の高いInnoDBといったストレージエンジンが使えるということです。
InnoDBの主な特徴としては次の通りです。
トランザクション対応である
クラッシュセーフである
更新と参照が入り乱れた場合の同時実行性能が良い
MySQL 5.1以降からの大幅な性能向上を果たしたInnoDBが使えるというだけでも、mroongaを導入する価値があります。
プラガブルストレージエンジンである
アップデートが容易なプラガブルストレージエンジン、つまりプラグイン形式であることもメリットの一つです。TritonnのようなMySQLのソースに手を入れるパッチ形式ではないため、MySQL本体のバージョンアップが容易です。
bigram以外の豊富なN-gramトークナイザが利用可能
Tritonnではmecab、bigramとdelimited(空白区切り)のみの対応でした。mroongaではそれだけでなく、uni-gram、tri-gramの他、多数の派生N-gramでのトークナイズに対応しています。
デフォルトはparser "TokenBigram"
が指定されているものとして動作しますが、次のように指定することもできます。
CREATE TABLE search (
id INT PRIMARY KEY AUTO_INCREMENT ,
content VARCHAR ( 255 ),
FULLTEXT INDEX ( content ) COMMENT 'parser "TokenUnigram"'
) ENGINE = mroonga DEFAULT CHARSET = utf8 ;
より強化された文字列正規化機能が利用可能
Tritonnでは、MySQLが提供するcollate(照合順序)と呼ばれる文字列正規化機能がデフォルトで働いており、NO NORMALIZE
と指定することで無効化される挙動でした。
mroongaでは全文検索機能を完全に外部で持つため、指定のない場合にはgroonga独自のnormalizer(NormalizerAuto)を利用します。これは、大文字・小文字だけでなく、全角・半角を同一視できるというUnicodeのNFKCを用いたとても便利な機能です。
しかしながら、これまで同様の正規化機能が必要な場合には、別途groonga-normalizer-mysql
パッケージをインストールの上、次のようにインデックスコメントにて、COMMENT 'normalizer "NormalizerMySQLGeneralCI"'
のように指定しましょう。
CREATE TABLE search (
id INT PRIMARY KEY AUTO_INCREMENT ,
content VARCHAR ( 255 ),
FULLTEXT INDEX ( content ) COMMENT 'normalizer "NormalizerMySQLGeneralCI"'
) ENGINE = mroonga DEFAULT CHARSET = utf8 ;
より具体的な挙動の違いに関しては、groonga/mroongaの文字列正規化機能 (normalizer) の挙動を追ってみる の記事が参考になります。
位置情報検索に対応
mroongaのストレージモード・ラッパーモード共に、SPATIAL INDEXに対するMBRContains関数を用いた位置情報検索 に対応しています。ストレージモードであればPOINT型を、InnoDBラッパーモードであればGEOMETRY型を指定します。
テーブルのスキーマは次のように定義します。
CREATE TABLE shops (
id INT PRIMARY KEY AUTO_INCREMENT ,
name VARCHAR ( 255 ),
location POINT NOT NULL ,
SPATIAL INDEX ( location )
) ENGINE = mroonga ;
CREATE TABLE shops (
id INT PRIMARY KEY AUTO_INCREMENT ,
name TEXT ,
location GEOMETRY NOT NULL ,
SPATIAL INDEX location_index ( location )
) ENGINE = mroonga comment = 'engine "innodb"' ;
データの登録・検索は次のように行います。
INSERT INTO shops VALUES ( null , 'Naniwaya' , GeomFromText ( 'POINT(139.796234 35.730061)' ));
SELECT id , name , AsText ( location ) AS location_text FROM shops
WHERE MBRContains ( GeomFromText ( 'LineString(139.7101 35.7292, 139.7662 35.6815)' ), location );
ただし、データとして格納できるのはPOINT(GEOMETRY)型のみで、LINEなどの他のデータ型は保存できないという制約があります。また、MBRDisjointなどにも対応していません。GEOMETRY型についての詳細は、第5回 位置情報を保存しよう(前編) :位置情報サービスのはじめ方 が参考になります。
汎用的に矩形での位置情報検索をするなら、B-Treeを用いた前方一致探索のできるGeoHash という手法があります。このGeoHashの具体的な使い方に関しては、第6回 位置情報を保存しよう(後編) :位置情報サービスのはじめ方 が参考になります。
移行する際に気をつけたいポイント
ストレージモードとラッパーモード
ストレージモードとは、MySQLのデータベースを利用せずに、groongaのデータベースに全データを格納して利用するモードです。参照ロックフリーの恩恵を受けられるなどのメリットは多くありますが、データ型は厳密にMySQLと同一の挙動を示すわけではありません。
そういった事情もあり、私としてはTritonnからの移行を行うなら、ラッパーモードの利用をお勧めしたいです。
ラッパーモードで使うストレージエンジン
COMMENT='engine "innodb"'
のように、テーブルのスキーマにて指定ができます。次のサンプルではinnodbを指定していますが、myisamなど、どんなストレージエンジンの利用も可能です。
CREATE TABLE search (
id INT PRIMARY KEY AUTO_INCREMENT ,
content VARCHAR ( 255 ),
FULLTEXT INDEX ( content )
) ENGINE = mroonga DEFAULT CHARSET = utf8 COMMENT = 'engine "innodb"' ;
ストレージエンジンをMyISAMからInnoDBへ切り替える際の注意
mroongaと間接的に関わる話として、MyISAMからInnoDBへ乗り換えるときにハマりやすい挙動の違いを紹介します。それは、Auto Incrementの挙動がMyISAMとInnoDBで異なるということです。 Tritonn/MyISAMを利用しているシステムをInnoDB化する際、次の2点について確認が必要です。
以下に該当するクエリを利用している
INSERT IGNORE INTO ...
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
LOAD DATA ... IGNORE INTO ...
行削除するケースがある
具体的にどのような挙動の違いがあるか、次のテーブルを利用して説明します。
CREATE TABLE test (
id INT PRIMARY KEY AUTO_INCREMENT ,
name VARCHAR ( 10 ),
UNIQUE INDEX ( name )
) ENGINE = InnoDB DEFAULT CHARSET = utf8 ;
IGNORE INTO文の動作の違い
INSERT IGNORE INTO ...
を用いて解説します。なお、INSERT INTO ... ON DUPLICATE KEY UPDATE ...
の挙動も同一です。
mysql > INSERT IGNORE INTO test ( name ) VALUES ( 'トマト' );
Query OK , 1 row affected ( 0.00 sec )
mysql > SELECT LAST_INSERT_ID ()\ G
*************************** 1. row ***************************
LAST_INSERT_ID (): 1
1 row in set ( 0.00 sec )
mysql > INSERT IGNORE INTO test ( name ) VALUES ( 'トマト' );
Query OK , 0 rows affected ( 0.00 sec )
mysql > SELECT LAST_INSERT_ID ()\ G
*************************** 1. row ***************************
LAST_INSERT_ID (): 1
1 row in set ( 0.00 sec )
mysql > INSERT IGNORE INTO test ( name ) VALUES ( 'トマト2' );
Query OK , 1 row affected ( 0.00 sec )
mysql > SELECT LAST_INSERT_ID ()\ G
*************************** 1. row ***************************
LAST_INSERT_ID (): 3
1 row in set ( 0.00 sec )
mysql > select * from test ;
+
| id | name |
+
| 1 | トマト |
| 3 | トマト 2 |
+
2 rows in set ( 0.00 sec )
データを削除した時のプライマリキーの挙動の違い
InnoDBの場合、Auto Incrementで取る値は保持されません。MySQLを一度終了すると、実際に格納されている主キーの最大値+1に自動調整となる挙動を示します。
具体例とともに解説します。
mysql > INSERT INTO test ( name ) VALUES ( 'トマト1' );
Query OK , 1 row affected ( 0.02 sec )
mysql > INSERT INTO test ( name ) VALUES ( 'トマト2' );
Query OK , 1 row affected ( 0.02 sec )
mysql > SELECT LAST_INSERT_ID ()\ G
*************************** 1. row ***************************
LAST_INSERT_ID (): 2
1 row in set ( 0.00 sec )
mysql > DELETE FROM test WHERE name IN ( 'トマト2' );
Query OK , 1 row affected ( 0.03 sec )
mysql > INSERT INTO test ( name ) VALUES ( 'トマト3' );
Query OK , 1 row affected ( 0.03 sec )
mysql > SELECT LAST_INSERT_ID ()\ G
*************************** 1. row ***************************
LAST_INSERT_ID (): 3
1 row in set ( 0.00 sec )
mysql > DELETE FROM test WHERE name IN ( 'トマト3' );
Query OK , 1 row affected ( 0.02 sec )
mysql > INSERT INTO test ( name ) VALUES ( 'トマト4' );
Query OK , 1 row affected ( 0.03 sec )
mysql > SELECT LAST_INSERT_ID ()\ G
*************************** 1. row ***************************
LAST_INSERT_ID (): 2
1 row in set ( 0.00 sec )
mysql > select * from test ;
+
| id | name |
+
| 1 | トマト 1 |
| 2 | トマト 4 |
+
2 rows in set ( 0.01 sec )
この挙動となる仕組みについては、MySQLリファレンスマニュアルのAUTO_INCREMENT カラムが InnoDB 内でどのように機能するか にて解説されています。
なお、mroongaのストレージモードも、このInnoDBと同じ挙動となります。これらの挙動によるトラブルが想定できる場合、ラッパーモードを利用した上でストレージエンジンをMyISAMにした方が良いでしょう。COMMENT='engine "myisam"'
と指定することで、引き続きMyISAMを利用できます。
その他、MyISAMとInnoDBの違いを8つの角度から解説している漢(オトコ)のコンピュータ道: MyISAMからInnoDBへ切り替えるときの注意点 も併せてご参照ください。
パーティショニング
InnoDBラッパーモードそのものでは、パーティショニングに対応していません。もしパーティショニングが必要な場合には、Spider 3.0と組み合わせることで実現できます。
具体的な方法に関しては、mroongaってなんじゃ?(Spiderで分散全文検索) を参照ください。
まとめと次回予告
今回はTritonnとmroongaそれぞれの紹介と移行時の要注意点、現在利用できる日本語全文検索ソリューションの比較を行いました。
次回は、より具体的なシステム移行に関するお話をお届けする予定です。ご期待ください。
groongaの利用事例を寄稿しませんか
連載の目的は「読者の皆さんがgroongaを使いたくなる!」ことです。そこで、すでにgroongaを使っており、groongaの利用事例を本連載で紹介していただける人を募集します。募集要項 を参考にご連絡ください。お待ちしています!