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


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

groongaやmroongaを実際に使っていて、記事を書いてもいいよ、という人を募集しています。
詳細は[groonga普及のための協力のお願い](http://sourceforge.jp/projects/groonga/lists/archive/dev/2013-February/001186.html)を参照してください。

# はじめに

MySQLで高速に全文検索するためのオープンソースのストレージエンジンとして[mroonga](http://mroonga.github.com/ja/)を公開しています。最新のバージョンは2013年2月9日にリリースしたmroonga [3.00](http://mroonga.github.com/ja/blog/2013/02/09/release.html)です。

mroonga 3.00では、文字列を比較したり並べ替えるときに使われるCOLLATION(照合順序)のうち、 *utf8_general_ci* と *utf8mb4_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* テーブルを作成します。

```sql
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;
```

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

```sql
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 ('Ａ','全角大文字');
insert into test_collate (val, note) values ('ａ','全角小文字');
```

"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 | 全角大文字             | Ａ   |
> |  6 | 全角小文字             | ａ   |
> +----+------------------------+------+
> 4 rows in set (0.00 sec)
> 

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

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

```sql
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);
```

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

```sql
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 ('Ａ','全角大文字');
insert into test_collate (val2, note) values ('ａ','全角小文字');

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 ('Ａ','全角大文字');
insert into test_collate (val3, note) values ('ａ','全角小文字');
```

追加したカラムに対しても"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 | 全角大文字             |      | Ａ   |      |
> | 12 | 全角小文字             |      | ａ   |      |
> +----+------------------------+------+------+------+
> 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に興味を持ったなら、まずは[インストール](http://mroonga.github.com/ja/docs/install.html)して試してみてください。

[ユーザーガイド](http://mroonga.github.com/ja/docs/userguide.html)も用意しています。