かみぽわーる

kamipo's blog

MySQL と Unicode Collation Algorithm (UCA)

utf8_unicode_ci に対する日本の開発者の見解 - かみぽわーる で、日本語が分かる人には utf8_unicode_ci のヤバさを感じてもらえたと思うんですけど、この挙動はドキュメントによると UCA というアルゴリズムによるものらしい。

MySQL implements the xxx_unicode_ci collations according to the Unicode Collation Algorithm (UCA) described at http://www.unicode.org/reports/tr10/. The collation uses the version-4.0.0 UCA weight keys: http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt. Currently, the xxx_unicode_ci collations have only partial support for the Unicode Collation Algorithm. Some characters are not supported yet. Also, combining marks are not fully supported. This affects primarily Vietnamese, Yoruba, and some smaller languages such as Navajo. http://dev.mysql.com/doc/refman/5.6/en/charset-unicode-sets.html

これもしかして、 Unicode って日本語のこと分かってない人たちによって作られてて日本語の検索とかなんも考慮されてないんとちゃうんかと思って調べてみたら、 そんなことはまったくなくて MySQL が UCA を部分的にしか実装していないということだった。

UTS #10: Unicode Collation Algorithm によると、 UCA では Multi-Level Comparison といって複数レベルに分けて文字列の比較を行い、各レベルの比較で文字列が一致した場合(tie-breaking level)、次のレベルで比較を行うを繰り返して順序を決定する。L1は大文字小文字アクセント無視(Base Charaters)、L2はアクセントを無視しない(Accents)、L3は大文字小文字を無視しない(Case/Variants)、のような感じである。

MySQL が UCA を部分的にしか実装していないとはどういうことかというと、 allkeys.txt でいうところの Primary weight range (L1比較のためのweight) しか実装していないので、アクセントを区別しないと常用に適さない言語(日本語とか)殺しな挙動になっているということだった。

mysql-5.7.6/strings/ctype-uca.c#L17-L31 からコメントを引用する。

/* 
   UCA (Unicode Collation Algorithm) support. 
   Written by Alexander Barkov <bar@mysql.com>
   
   Currently supports only subset of the full UCA:
   - Only Primary level key comparison
   - Basic Latin letters contraction is implemented
   - Variable weighting is done for Non-ignorable option
   
   Features that are not implemented yet:
   - No Normalization From D is done
     + No decomposition is done
     + No Thai/Lao orderding is done
   - No combining marks processing is done
*/

アクセントを区別しないと常用に適さない言語が日本語以外にどれぐらいあるのか言語に詳しくないので分からないけど、これを理由に以下のコミットをrevertできたりしないですかね。

参考