LoginSignup
3
3

More than 5 years have passed since last update.

mroongaでMySQL互換の照合順序を使うには

Posted at

もっとgroongaを知ってもらおう!ということで週刊groongaをはじめました。毎週木曜にgroongaやmroongaのトピックを投稿予定です。

groongaやmroongaを実際に使っていて、記事を書いてもいいよ、という人を募集しています。
詳細はgroonga普及のための協力のお願いを参照してください。

はじめに

MySQLで高速に全文検索するためのオープンソースのストレージエンジンとしてmroongaを公開しています。最新のバージョンは2013年2月9日にリリースしたmroonga 3.00です。

mroonga 3.00では、文字列を比較したり並べ替えるときに使われるCOLLATION(照合順序)のうち、 utf8_general_ciutf8mb4_general_ci をサポートしました。

照合順序として utf8_general_ci もしくは utf8mb4_general_ci を使いたい場合には、 groonga-normalizer-mysql パッケージをあらかじめインストールしておく必要があります。

COLLATIONを使うと大文字小文字の区別なく比較(例えば、Aとaを同一視する)することができます。例の場合はgroongaのnormalizerが提供している機能と同じです。

ただし、mroongaではgroongaのnormalizerを使って同一視する文字を判定し、その結果のソートはMySQLにやってもらうという役割を分担した仕組みになっています。

そのため、groongaのnormalizerとMyISAMやInnoDBとで同一視する文字が異なっていると、仕組み上他のストレージエンジンを使った場合と結果が異なるという問題がありました。

今回の改良でMyISAMでもInnoDBでもmroongaでも同じ文字を同一視するようになりました。

例えば、「a」(U+0061 LATIN SMALL LETTER A)は「A」(U+0041 LATIN CAPITAL LETTER A)だけではなく、「à」(U+00E0 LATIN SMALL LETTER A WITH GRAVE)や「Á」(U+00C1 LATIN CAPITAL LETTER A WITH ACUTE)とも同一視されます。

この変更は非互換な変更です。

上記の違いを実際に比べてみましょう。

1つ前のmroonga 2.10であらかじめ以下のSQLで test_collate テーブルを作成します。

use test;
drop table IF EXISTS test_collate;
create table test_collate (
id            int primary key auto_increment,
note          text,
val           varchar(4),
FULLTEXT INDEX(val)
) engine=mroonga default charset utf8;

次に、サンプルデータを投入します。

use test;
insert into test_collate (val, note) values ('A','LATIN CAPITAL LETTER A');
insert into test_collate (val, note) values ('a','LATIN SMALL LETTER A');
insert into test_collate (val, note) values (_utf8 x'c3a0','LATIN SMALL LETTER A WITH GRAVE');
insert into test_collate (val, note) values (_utf8 x'c381','LATIN CAPITAL LETTER A WITH
ACUTE');
insert into test_collate (val, note) values ('A','全角大文字');
insert into test_collate (val, note) values ('a','全角小文字');

"a"にマッチするものを検索すると「à」(U+00E0 LATIN SMALL LETTER A WITH GRAVE)や「Á」(U+00C1 LATIN CAPITAL LETTER A WITH ACUTE)は検索結果に含まれないことがわかります。

mysql> select * from test_collate where match (val) against ("a");
+----+------------------------+------+
| id | note | val |
+----+------------------------+------+
| 1 | LATIN CAPITAL LETTER A | A |
| 2 | LATIN SMALL LETTER A | a |
| 5 | 全角大文字 | A |
| 6 | 全角小文字 | a |
+----+------------------------+------+
4 rows in set (0.00 sec)

次に、 groonga-normalizer-mysql パッケージをインストールし、mroongaを3.00にアップグレードします。

その後、ALTER TABLEで新規にカラムを追加します。

use test;
ALTER TABLE test_collate ADD val2 varchar(4) COLLATE 'utf8_roman_ci';
ALTER TABLE test_collate ADD FULLTEXT INDEX val2_idx (val2);
ALTER TABLE test_collate ADD val3 varchar(4) COLLATE 'utf8_general_ci';
ALTER TABLE test_collate ADD FULLTEXT INDEX val3_idx (val3);

追加したカラムへサンプルデータを投入します。

use test;
insert into test_collate (val2, note) values ('A','LATIN CAPITAL LETTER A');
insert into test_collate (val2, note) values ('a','LATIN SMALL LETTER A');
insert into test_collate (val2, note) values (_utf8 x'c3a0','LATIN SMALL LETTER A WITH GRAVE');
insert into test_collate (val2, note) values (_utf8 x'c381','LATIN CAPITAL LETTER A WITH ACUTE');
insert into test_collate (val2, note) values ('A','全角大文字');
insert into test_collate (val2, note) values ('a','全角小文字');

insert into test_collate (val3, note) values ('A','LATIN CAPITAL LETTER A');
insert into test_collate (val3, note) values ('a','LATIN SMALL LETTER A');
insert into test_collate (val3, note) values (_utf8 x'c3a0','LATIN SMALL LETTER A WITH GRAVE');
insert into test_collate (val3, note) values (_utf8 x'c381','LATIN CAPITAL LETTER A WITH ACUTE');
insert into test_collate (val3, note) values ('A','全角大文字');
insert into test_collate (val3, note) values ('a','全角小文字');

追加したカラムに対しても"a"でマッチするか確認します。

mysql> select * from test_collate where match(val2) against("a");
+----+------------------------+------+------+------+
| id | note | val | val2 | val3 |
+----+------------------------+------+------+------+
| 7 | LATIN CAPITAL LETTER A | | A | |
| 8 | LATIN SMALL LETTER A | | a | |
| 11 | 全角大文字 | | A | |
| 12 | 全角小文字 | | a | |
+----+------------------------+------+------+------+
4 rows in set (0.00 sec)

mysql> select * from test_collate where match(val3) against("a");
+----+-----------------------------------+------+------+------+
| id | note | val | val2 | val3 |
+----+-----------------------------------+------+------+------+
| 13 | LATIN CAPITAL LETTER A | | | A |
| 14 | LATIN SMALL LETTER A | | | a |
| 15 | LATIN SMALL LETTER A WITH GRAVE | | | à |
| 16 | LATIN CAPITAL LETTER A WITH ACUTE | | | Á |
+----+-----------------------------------+------+------+------+
4 rows in set (0.00 sec)

新規追加したカラムに関して、 utf8_roman_ci を指定するとgroongaのnormalizerが使われ(従来通りの挙動)、 utf8_general_ci を指定するとMySQL互換の結果になっていることがわかります。

既存のデータベースへの影響について

新しく作成するテーブル・カラム・インデックスから有効になります。
すでに存在しているカラム・インデックスはこれまで通り、groonga独自のnormalizer(NormalizerAuto)が使われます。

そのため、mroongaを3.00へとアップデートして既存のデータベースを使い続けるとカラム毎に異なるnormalizerを使うことになる点に注意が必要です。

全体で同じnormalizerを使う方法について

新しく作るテーブル・カラム・インデックスのCOLLATIONとして utf8_roman_ci など utf8_general_ci ではないCOLLATIONを指定するとgroongaのnormalizerに統一(従来通りの挙動)できます。

まとめ

mroongaでMySQL互換のCOLLATIONを使う方法を紹介しました。

mroongaに興味を持ったなら、まずはインストールして試してみてください。

ユーザーガイドも用意しています。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3