Slide 1

Slide 1 text

MySQLと令和 MySQLと令和 とみたまさひろ 2019-08-10 NSEG 1

Slide 2

Slide 2 text

自己紹介 自己紹介 とみたまさひろ プログラマー? 富士通クラウドテクノロジーズ 日本MySQLユーザ会 得意技: Ruby, 文字化け @tmtms https://tmtm.github.io/mysql-params/ https://tmtm.github.io/postfix-params/ 2

Slide 3

Slide 3 text

㊗令和元年 ㊗令和元年 3

Slide 4

Slide 4 text

今日は「令和」の話をします 今日は「令和」の話をします 4

Slide 5

Slide 5 text

その1 その1 「令和」と言えば… 「令和」と言えば… 5

Slide 6

Slide 6 text

似てるけど違う文字 似てるけど違う文字 「令」と「令」 「令」と「令」 6

Slide 7

Slide 7 text

同じに見えるけど別の文字 同じに見えるけど別の文字 「令」 U+4EE4 CJK UNIFIED IDEOGRAPH 「令」 U+F9A8 CJK COMPATIBILITY IDEOGRAPH 困る! 7

Slide 8

Slide 8 text

MySQLでは MySQLでは 一致 mysql> set @a='令和', @b='令和'; mysql> select @a, @b, hex(@a), hex(@b); +--------+--------+--------------+--------------+ | @a | @b | hex(@a) | hex(@b) | +--------+--------+--------------+--------------+ | 令和 | 令和 | E4BBA4E5928C | EFA6A8E5928C | +--------+--------+--------------+--------------+ mysql> select @a=@b; +-------+ | @a=@b | +-------+ | 1 | ← ❗❗ +-------+ 8

Slide 9

Slide 9 text

9

Slide 10

Slide 10 text

その2 その2 「令和」と言えば… 「令和」と言えば… 10

Slide 11

Slide 11 text

異体字 異体字 「 「令 令」と「 」と「 」 」 11

Slide 12

Slide 12 text

違う字形だけど同じ文字 違う字形だけど同じ文字 異体字セレクタ 「令」 U+4EE4 「令」 U+4EE4 U+E0101 「 」 U+4EE4 U+E0102 困る! 12

Slide 13

Slide 13 text

MySQLでは MySQLでは ※都合により同じ字体に見えてます 一致 mysql> set @a='令和', @b='令 和', @c='令 和'; mysql> select hex(@a), hex(@b), hex(@c)\G *************************** 1. row *************************** hex(@a): E4BBA4E5928C hex(@b): E4BBA4F3A08481E5928C hex(@c): E4BBA4F3A08482E5928C mysql> select @a=@b, @b=@c; +-------+-------+ | @a=@b | @b=@c | +-------+-------+ | 1 | 1 | ← ❗❗ +-------+-------+ 13

Slide 14

Slide 14 text

14

Slide 15

Slide 15 text

その3 その3 「令和」と言えば… 「令和」と言えば… 15

Slide 16

Slide 16 text

元号 元号 16

Slide 17

Slide 17 text

元号と言えば… 元号と言えば… 17

Slide 18

Slide 18 text

合字 合字 明治(U+660E U+6CBB) ㍾(U+337E) ⼤正(U+5927 U+6B63) ㍽(U+337D) 昭和(U+662D U+548C) ㍼(U+337C) 平成(U+5E73 U+6210) ㍻(U+337B) 令和(U+4EE4 U+548C) ㋿(U+32FF) 18

Slide 19

Slide 19 text

MySQLでは MySQLでは mysql> select '明治'='㍾', '大正'='㍽', '昭和'='㍼', -> '平成'='㍻', '令和'='㋿'\G *************************** 1. row *************************** '明治'='㍾': 1 ← 一致❗ '大正'='㍽': 1 ← 一致❗ '昭和'='㍼': 1 ← 一致❗ '平成'='㍻': 1 ← 一致❗ '令和'='㋿': 0 ← 不一致❗ 19

Slide 20

Slide 20 text

20

Slide 21

Slide 21 text

なにが起きてるのか? なにが起きてるのか? 21

Slide 22

Slide 22 text

MySQL は Unicode 9.0.0 準拠 MySQL は Unicode 9.0.0 準拠 22

Slide 23

Slide 23 text

Unicodeの照合順序 Unicodeの照合順序 Unicode Collation Algorithm (UCA) Default Unicode Collation Element Table (DUCET) 文字毎にWeightという値が定義されている Weightが等しいなら等しい文字 https://unicode.org/reports/tr10/tr10-34.html https://www.unicode.org/Public/UCA/9.0.0/allkeys.txt 23

Slide 24

Slide 24 text

その1 その1 似てるけど違う文字 似てるけど違う文字 「令」と「令」 「令」と「令」 24

Slide 25

Slide 25 text

「令」 U+4EE4 CJK UNIFIED IDEOGRAPH DUCETには無いけど計算で求まる 「令」 U+F9A8 CJK COMPATIBILITY IDEOGRAPH DUCETにある Weightが一致するから等しい [.FB40.0020.0002][.(CP | 0x8000).0000.0000] → [.FB40.0020.0002][.CEE4.0000.0000] F9A8 ; [.FB40.0020.0002][.CEE4.0000.0000] 25

Slide 26

Slide 26 text

その2 その2 異体字 異体字 「 「令 令」と「 」と「 」 」 26

Slide 27

Slide 27 text

異体字セレクタ 「令」 U+4EE4 「令」 U+4EE4 U+E0101 「 」 U+4EE4 U+E0102 異体字セレクタはDUCETにある UCAではすべてゼロの文字は無視 E0101 ; [.0000.0000.0000] # VARIATION SELECTOR-18 E0102 ; [.0000.0000.0000] # VARIATION SELECTOR-19 27

Slide 28

Slide 28 text

その3 その3 合字 合字 ㍾ / ㍽ / ㍼ / ㍻ / ㋿ 28

Slide 29

Slide 29 text

平成=㍻ 平成=㍻ 平成(U+5E73 U+6210): ㍻(U+337B) ちょっと違う… 平成 [.FB40.0020.0002][.DE73.0000.0000][.FB40.0020.0002][.E210.0000.0000] ㍻ [.FB40.0020.001C][.DE73.0000.0000][.FB40.0020.001C][.E210.0000.0000] 29

Slide 30

Slide 30 text

utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci MySQLのデフォルトのCollation 要素 意味 utf8mb4 4バイトUTF-8 0900 Unicode 9.0.0 ai アクセントの違いを無視 ci 大文字小文字の違いを無視 ciの場合はWeightの3番目を無視 30

Slide 31

Slide 31 text

ciの場合はWeightの3番目を無視 3番目を無視すると 一致 平成 [.FB40.0020.0002][.DE73.0000.0000][.FB40.0020.0002][.E210.0000.0000] ㍻ [.FB40.0020.001C][.DE73.0000.0000][.FB40.0020.001C][.E210.0000.0000] 平成 [.FB40.0020. ][.DE73.0000. ][.FB40.0020. ][.E210.0000. ] ㍻ [.FB40.0020. ][.DE73.0000. ][.FB40.0020. ][.E210.0000. ] 31

Slide 32

Slide 32 text

令和≠㋿ 令和≠㋿ そもそも「㋿」がDUCETに無い! 32

Slide 33

Slide 33 text

「㋿」はUnicode 9.0.0 に無い! 33

Slide 34

Slide 34 text

「㋿」はUnicode 12.1.0 で追加 12.1 は「㋿」のためだけに 5/7 にリリース http://unicode.org/versions/Unicode12.1.0/ Unicode 12.1 adds exactly one character, for a total of 137,929 characters. The new character added to Version 12.1 is: U+32FF SQUARE ERA NAME REIWA Version 12.1 adds that single character to enable software to be rapidly updated to support the new Japanese era name in calendrical systems and date formatting. The new Japanese era name was officially announced on April 1, 2019, and is effective as of May 1, 2019. 34

Slide 35

Slide 35 text

MySQL独自の変な挙動じゃなくて MySQL独自の変な挙動じゃなくて Unicodeの規則だった! Unicodeの規則だった! 35

Slide 36

Slide 36 text

Unicode規則にちゃんと従ってる Unicode規則にちゃんと従ってる MySQLえらい! MySQLえらい! 36

Slide 37

Slide 37 text

Collationについて学べる「令和」 Collationについて学べる「令和」 すごい! すごい! 37

Slide 38

Slide 38 text

おまけ おまけ 38

Slide 39

Slide 39 text

日本語Collation 日本語Collation 39

Slide 40

Slide 40 text

utf8mb4_ utf8mb4_ja ja_0900_as_cs _0900_as_cs utf8mb4_ utf8mb4_ja ja_0900_as_cs_ _0900_as_cs_ks ks 要素 意味 utf8mb4 4バイトUTF-8 ja 言語 0900 Unicode 9.0.0 as アクセント違いは別の文字 cs 大文字小文字は別の文字 ks 平仮名と片仮名は別の文字 40

Slide 41

Slide 41 text

JIS規則のCollation JIS規則のCollation 41

Slide 42

Slide 42 text

比較 ai_ci as_ci as_cs ja as_cs ja as_cs_ks bin A=a ◯ ◯ × × × × A=A ◯ ◯ × ◯ ◯ × A=a ◯ ◯ × × × × あ=ぁ ◯ ◯ × × × × あ=ア ◯ ◯ × ◯ × × は=ば=ぱ ◯ × × × × × 1=① ◯ ◯ × × × × 令=令 ◯ ◯ ◯ × × × 令= ◯ ◯ ◯ ◯ ◯ × 平成=㍻ ◯ ◯ × × × × 42

Slide 43

Slide 43 text

ソート順もJIS ソート順もJIS mysql> select c,hex(c) from t order by c; +------+--------+ | c | hex(c) | +------+--------+ | 亜 | E4BA9C | | 伊 | E4BC8A | | 宇 | E5AE87 | | 栄 | E6A084 | | 奥 | E5A5A5 | +------+--------+ 43

Slide 44

Slide 44 text

長音記号のソート順は前の文字の母音と同じ 長音記号のソート順は前の文字の母音と同じ mysql> select c from t2 order by c; +--------+ | c | +--------+ | かー | | かあ | | かい | | きあ | | きー | | きい | | くあ | | くい | | くー | +--------+ 44

Slide 45

Slide 45 text

業界によってはうれしいかも 業界によってはうれしいかも 45

Slide 46

Slide 46 text

業界によってはうれしいかも 業界によってはうれしいかも ちょっとやりすぎ感? ちょっとやりすぎ感? 45

Slide 47

Slide 47 text

業界によってはうれしいかも 業界によってはうれしいかも ちょっとやりすぎ感? ちょっとやりすぎ感? 文句はJISに 文句はJISに 45

Slide 48

Slide 48 text

おまけ2 おまけ2 46

Slide 49

Slide 49 text

utf8mb4_0900_bin utf8mb4_0900_bin MySQL 8.0.17 から登場 47

Slide 50

Slide 50 text

CollationのPAD属性 CollationのPAD属性 8.0 から追加 PAD SPACE - 末尾空白文字の有無を無視する 5.7までの振る舞い NO PAD - 末尾空白文字の有無を無視しない 8.0からの新しいCollation utf8mb4_*0900_* 48

Slide 51

Slide 51 text

PAD SPACE と NO PAD PAD SPACE と NO PAD mysql> set names utf8mb4 collate utf8mb4_unicode_520_ci; mysql> select 'a' = 'a '; +--------------+ | 'a' = 'a ' | +--------------+ | 1 | +--------------+ mysql> set names utf8mb4 collate utf8mb4_0900_ai_ci; mysql> select 'a' = 'a '; +--------------+ | 'a' = 'a ' | +--------------+ | 0 | +--------------+ 49

Slide 52

Slide 52 text

utf8mb4_0900_bin utf8mb4_0900_bin utf8mb4_bin にも NO PAD バージョンが欲しい 互換のために utf8mb4_bin は変更できない utf8mb4_0900_bin 新設 50

Slide 53

Slide 53 text

utf8mb4_bin と utf8mb4_0900_bin utf8mb4_bin と utf8mb4_0900_bin mysql> set names utf8mb4 collate utf8mb4_bin; mysql> select 'a' = 'a '; +--------------+ | 'a' = 'a ' | +--------------+ | 1 | +--------------+ mysql> set names utf8mb4 collate utf8mb4_0900_bin; mysql> select 'a' = 'a '; +--------------+ | 'a' = 'a ' | +--------------+ | 0 | +--------------+ 51

Slide 54

Slide 54 text

名前がイマイチな気がする 名前がイマイチな気がする 0900 は Unicode 9.0.0 準拠のCollationという意味 utf8mb4_0900_bin は Unicode 準拠じゃない NO PADなCollationは0900だけだからこうなった? それにしてもなー 52

Slide 55

Slide 55 text

まとめ まとめ 53

Slide 56

Slide 56 text

まとめ まとめ 適切なCollationを選ぼう! 適切なCollationを選ぼう! 53

Slide 57

Slide 57 text

まとめ まとめ 適切なCollationを選ぼう! 適切なCollationを選ぼう! Collation多すぎ? Collation多すぎ? 53

Slide 58

Slide 58 text

まとめ まとめ 適切なCollationを選ぼう! 適切なCollationを選ぼう! Collation多すぎ? Collation多すぎ? 実は全ての文字を区別できる 実は全ての文字を区別できる utf8mb4_0900_bin でよかったり? utf8mb4_0900_bin でよかったり? たぶん速いし たぶん速いし 53