MySQL 8.0.1では、utf8mb4の大文字小文字およびアクセント記号付きの文字を判別するas_cs collationに加えて、日本語用のCollation(文字照合順)を追加しました。
utf8mb4_ja_0900_as_csについて
日本語に関する文字照合およびソートのルールは複雑です。日本語ではひらがな、カタカナ、漢字、アルファベット(ラテン文字)を混在させて利用しています。さらに、全角と半角が存在する文字もあります。では、‘あ’, ‘ア’, ‘a’, ‘ア’はどのようにソートされるのでしょうか?
Unicode照合アルゴリズム(UCA / Unicode Collation Algorithm)の中で規定されているデフォルトUnicode照合基本テーブル(DUCET / Default Unicode Collation Element Table)にてUnicode文字列の比較アルゴリズムを定義しています。このDUCETは言語ごとにカスタマイズされた情報をXML形式で提供する共通ロケールデータリポジトリ(CLDR, Common Locale Data Repository)にて、日本語に関するソート順を定義した部分[reorder Latn Kana Hani]での日本語に関するソート順のルールによると、ラテン文字は全てのひらがなやカタカナよりも前に位置づけられているため‘a’が最初となります。では残りの‘あ’, ‘ア’, ‘ア’はどうなるでしょうか?ここでは以下のルールが適用されます: ‘&あ<<<<ア=ア’
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
mysql> set names utf8mb4; Query OK, 0 rows affected (0.00 sec) mysql> select strcmp('a', 'あ' collate utf8mb4_ja_0900_as_cs); +--------------------------------------------------+ | strcmp('a', 'あ' collate utf8mb4_ja_0900_as_cs) | +--------------------------------------------------+ | -1 | +--------------------------------------------------+ 1 row in set (0.00 sec) mysql> select strcmp('あ', 'ア' collate utf8mb4_ja_0900_as_cs); +----------------------------------------------------+ | strcmp('あ', 'ア' collate utf8mb4_ja_0900_as_cs) | +----------------------------------------------------+ | 0 | +----------------------------------------------------+ 1 row in set (0.00 sec) mysql> select strcmp('ア', 'ア' collate utf8mb4_ja_0900_as_cs); +----------------------------------------------------+ | strcmp('ア', 'ア' collate utf8mb4_ja_0900_as_cs) | +----------------------------------------------------+ | 0 | +----------------------------------------------------+ 1 row in set (0.00 sec) |
なぜ‘あ’, ‘ア’, ‘ア’は等価なのでしょうか?UCAではマルチレベルの比較アルゴリズムを使用して照合を個なっています。この比較アルゴリズムの4次レベルでは‘あ’が‘ア’よりも前に来るとされているにも関わらずです。ポイントはCLDRでは日本語の文字照合順の強度は3次レベルであると定義されています。従って4次レベルでの差は無視されることとなります。これはユーザーの期待した挙動ではないかもしれません。そこで我々は日本語を扱うMySQLユーザーの要望をもとにしたCollationをMySQL 8.0に追加することを検討しています。
日本工業規格の一つJIS X 0208 (http://www.jisc.go.jp/app/pager?id=94516)では、日本語の漢字6,355文字とそのソート順について定義しています。utf8mb4_ja_0900_as_csはこのJIS X 0208に準じた漢字のソートを行います。しかしこのJIS X 0208では含まれない漢字も多数存在します。これらの漢字についてutf8mb4_ja_0900_as_csはUCA(Unicode Collation Algorithm)で定義されたそれぞれの文字の重み(implicit weight) (http://www.unicode.org/reports/tr10/#Implicit_Weights)を利用します。
以下の文字を例にソート順を確認してみます: ‘王’, ‘人’, ‘兵’, ‘﨎’, ‘㐀’
最初の3文字はJIS X 0208で定義されていますが、残りの2文字は定義されていません。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
mysql> create table jpn(a varchar(10)) collate utf8mb4_ja_0900_as_cs; Query OK, 0 rows affected (0.90 sec) mysql> insert into jpn values ('王'), ('﨎'), ('人'), ('㐀'), ('兵'); Query OK, 5 rows affected (0.05 sec) Records: 5 Duplicates: 0 Warnings: 0 mysql> select a from jpn order by a; +------+ | a | +------+ | 王 | | 人 | | 兵 | | 﨎 | | 㐀 | +------+ 5 rows in set (0.02 sec) |
まとめ
この記事以外にもMySQL 8.0におけるUTF-8の改良に関する記事をこれまでにも公開しております。以下の記事についてもぜひご参照下さい。
- MySQL 8.0.1: Accent and case sensitive collations for utf8mb4
- MySQL 8.0 Collations: The devil is in the details.
- New collations in MySQL 8.0.0
- Sushi = Beer ?! An introduction of UTF8 support in MySQL 8.0
ぜひ新しいCollationをご利用いただき、またフィードバックをお送りいただければと思います。