MySQL Innovation Day Tokyo で MySQL 8 の文字コードについて話した

MySQL Innovation Day Tokyo に参加して10分ほど喋ってきました。

ひさびさに巨大サキラちゃん登場。本人曰く5年間ほど倉庫に隠れてたそうです。

f:id:tmtms:20180523175014j:plain

昼ごはんは今半のすき焼弁当でした。豪華!

f:id:tmtms:20180523121113j:plain f:id:tmtms:20180523121135j:plain

会場の様子。百数十人で満員でした f:id:tmtms:20180523152737j:plain

以下わたしの発表内容。スライドはこちら https://tmtm.github.io/mysql-innovation-tokyo/


MySQL恒例「RCとはいったい…」案件

utf8の指定でwarningが出るようになった

mysql> set names utf8;
Query OK, 0 rows affected, 1 warning (0.00 sec)

Warning (Code 3719): 'utf8' is currently an alias for the character set UTF8MB3, which will be replaced by UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.

今は utf8 は utf8mb3 の別名だけどどうやら将来 utf8mb4 の別名になるらしく、そのためのwarningらしいんだけど、RC版では出力されなかったのがGA版で出力されるようになったのはいいんだろうか。

なお、utf8mb3 を使えという割には、参照時には utf8 と表示されるのがイマイチ。show create table の結果をそのまま使うと warning が出るという…。

mysql> create table xx (id char(10)) charset utf8mb3;
Query OK, 0 rows affected (0.08 sec)

mysql> show create table xx\G
*************************** 1. row ***************************
       Table: xx
Create Table: CREATE TABLE `xx` (
  `id` char(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

mysql> CREATE TABLE `xx` (
    ->   `id` char(10) DEFAULT NULL
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected, 1 warning (0.19 sec)

Warning (Code 3719): 'utf8' is currently an alias for the character set UTF8MB3, which will be replaced by UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.

mysqlshのプロンプトが派手になった

プロンプトの「MySQL」の文字色がロゴの色と同じ。凝りすぎでは…。

f:id:tmtms:20180524223644p:plain

パラメータ比較

MySQLのバージョン間のパラメータを比較できるページを作りました。よろしければどうぞ。

https://tmtm.github.io/mysql-params/?vers=5.7.22,8.0.11&diff=true

RC版とGA版の比較はこちら。RCとはいったい…。

https://tmtm.github.io/mysql-params/?vers=8.0.4,8.0.11&diff=true

文字コードまわり

5.7ではデフォルトのcharsetはlatin1(ISO8859-1)だったのが8.0ではutf8mb4(Unicode)になった。

デフォルトのままで日本語や絵文字が使えるようになったのはよい。

utf8mb4 charset のcollation(照合規則)のうち日本語環境で使われそうなものは次の通り:

  • utf8mb4_bin
  • utf8mb4_general_ci (5.7 デフォルト)
  • utf8mb4_unicode_ci
  • utf8mb4_unicode_520_ci
  • utf8mb4_0900_ai_ci (8.0 デフォルト)
  • utf8mb4_0900_as_ci
  • utf8mb4_0900_as_cs
  • utf8mb4_ja_0900_as_cs
  • utf8mb4_ja_0900_as_cs_ks

強調されてる下の5つが8.0で増えたもの。

utf8mb4の次の文字の意味:

bin コードのまま
general MySQL独自規則
unicode Unicode 4.0.0
unicode_0520 Unicode 5.2.0
0900 Unicode 9.0.0
ja_0900 Unicode 9.0.0 + 日本語

その次の文字の意味:

ai Accent Insensitive アクセント違いは同じ文字
as Accent Sensitive アクセント違いは異なる文字
ci Case Insensitive 大文字小文字は同じ文字
cs Case Sensitive 大文字小文字は異なる文字
ks Kana Sensitive カタカナひらがなは異なる文字

デフォルトCollationの違い

  • 5.7: utf8mb4_general_ci

    • Aa, ,
    • 🍣🍺
  • 8.0: utf8mb4_0900_ai_ci

    • Aa, ,
    • 🍣🍺

Charset=utf8mb4 を指定しただけでは 5.7 と 8.0 で動きが異なるので注意

新しいCollationたち

utf8mb4_0900_ai_ci

  • アクセントの違いを区別しない

    • ははぱぱばば
  • 大文字小文字を区別しない

    • びょういんびよういん
    • いろはイロハ
    • 株式会社

ci/cs でカタカナや組文字も影響うけるらしい。

utf8mb4_0900_as_ci

  • アクセントの違いを区別する

    • ははぱぱばば
  • 大文字小文字を区別しない

    • びょういんびよういん
    • いろはイロハ
    • 株式会社

utf8mb4_0900_as_cs

  • アクセントの違いを区別する

    • ははぱぱばば
  • 大文字小文字を区別する

    • びょういんびよういん
    • いろはイロハ
    • 株式会社

(時間の都合で発表では以下は省略した)

全部の文字が区別されるんなら utf8mb4_bin と何が違う? 合成文字の扱いが異なる。

「が」と「か」+「゛」の比較

utf8mb4_0900_as_cs では一致:

mysql> set @a='が' collate utf8mb4_0900_as_cs;
mysql> set @b=concat('か', _utf8mb4 0xE38299 collate utf8mb4_0900_as_cs);
mysql> select @a,@b,hex(@a),hex(@b),@a=@b;
+------+--------+---------+--------------+-------+
| @a   | @b     | hex(@a) | hex(@b)      | @a=@b |
+------+--------+---------+--------------+-------+
| が   | が   | E3818C  | E3818BE38299 |     1 |
+------+--------+---------+--------------+-------+

utf8mb4_bin では不一致:

mysql> set @a='が' collate utf8mb4_bin;
mysql> set @b=concat('か', _utf8mb4 0xE38299 collate utf8mb4_bin);
mysql> select @a,@b,hex(@a),hex(@b),@a=@b;
+------+--------+---------+--------------+-------+
| @a   | @b     | hex(@a) | hex(@b)      | @a=@b |
+------+--------+---------+--------------+-------+
| が   | が   | E3818C  | E3818BE38299 |     0 |
+------+--------+---------+--------------+-------+

異体字セレクタも同様。

utf8mb4_ja_0900_as_cs

  • アクセントの違いを区別する

    • ははぱぱばば
  • 大文字小文字を区別する

    • びょういんびよういん
    • 株式会社
  • カタカナひらがなを区別しない

    • いろはイロハ

utf8mb4_ja_0900_as_cs_ks

  • アクセントの違いを区別する

    • ははぱぱばば
  • 大文字小文字を区別する

    • びょういんびよういん
    • 株式会社
  • カタカナひらがなを区別する

    • いろはイロハ

全部の文字が区別されるなら utf8mb4_0900_as_cs と同じ??

utf8mb4_0900 と utf8mb4_ja_0900 の違い

ja_0900 ではJISコード順にソートされる。

mysql> select hex(s),s from ja order by s;
+--------+------+
| hex(s) | s    |
+--------+------+
| E4BA9C | 亜   |
| E4BC8A | 伊   |
| E99BA8 | 雨   |
| E6A084 | 栄   |
| E5A5A5 | 奥   |
+--------+------+

長音記号は前の文字の母音に依存する。

mysql> select s from ja order by s;
+--------+
| s      |
+--------+
| あー   |
| ああ   |
| あい   |
| いあ   |
| いー   |
| いい   |
| うあ   |
| うい   |
| うー   |
+--------+

凝りすぎ!? でもこれはMySQL固有の特殊な実装じゃなくて、ちゃんとUnicodeの規約通り。 日本語辞書順ともいうらしい。

でも自分はつかわないかなー。

utf8mb4_0900_as_csが一番無難かも。 合成文字等の Unicode の特殊な事情を考慮しなくていいのであれば utf8mb4_binでもいいかも。たぶんその方が速いんじゃないかと。

昔からMySQLを使ってる人は大文字小文字を区別しない方がうれしいかもしれない。その場合は utf8mb4*ci の中から選択する感じで。

ちゃんと各collationの特徴を知って適切なものを使いましょう。


サキラちゃんと。

f:id:tmtms:20180523175456j:plain