TL;DR
- MySQL 8.0からデフォルトの照合順序が
latin1_swedish_ci
から utf8mb4_0900_ai_ci
になった
- さすがに
latin1
をそのまま使っているとは思えないけれど、 utf8mb4
だけで見てもデフォルトは utf8mb4_general_ci
から utf8mb4_0900_ai_ci
に変更になっている
- 「思ったよりは遅くならない」と見るか、「そんなに遅くなるのか」と見るかは人による気がする
まずは等価比較。
それぞれ10億回繰り返しているので、1回当たりの時間はナノ秒単位になる。
あと、データは保管せずただ比較しているだけなので、単純にCPU勝負のワークロードになる。
mysql80 8> SELECT BENCHMARK(1000000000, '1' = '1' COLLATE utf8mb4_0900_ai_ci) AS utf8mb4_0900_ai_ci; -- 8.0のデフォルト
+--------------------+
| utf8mb4_0900_ai_ci |
+--------------------+
| 0 |
+--------------------+
1 row in set (41.11 sec)
mysql80 8> SELECT BENCHMARK(1000000000, '1' = '1' COLLATE utf8mb4_general_ci) AS utf8mb4_general_ci; -- 5.7までで指定せずにutf8mb4にした時はこれ
+--------------------+
| utf8mb4_general_ci |
+--------------------+
| 0 |
+--------------------+
1 row in set (23.73 sec)
mysql80 8> SELECT BENCHMARK(1000000000, '1' = '1' COLLATE utf8mb4_bin) AS utf8mb4_bin; -- みんなだいすきbin
+-------------+
| utf8mb4_bin |
+-------------+
| 0 |
+-------------+
1 row in set (17.75 sec)
mysql80 8> SELECT BENCHMARK(1000000000, '1' = '1' COLLATE utf8mb4_ja_0900_as_cs) AS utf8mb4_ja_0900_as_cs; -- ハハ != パパ
+-----------------------+
| utf8mb4_ja_0900_as_cs |
+-----------------------+
| 0 |
+-----------------------+
1 row in set (1 min 22.47 sec)
mysql80 8> SET NAMES latin1;
Query OK, 0 rows affected (0.00 sec)
mysql80 8> SELECT BENCHMARK(1000000000, '1' = '1' COLLATE latin1_swedish_ci) AS latin1_swedish_ci; -- 一応latin1も
+-------------------+
| latin1_swedish_ci |
+-------------------+
| 0 |
+-------------------+
1 row in set (17.56 sec)
17nsが82nsになったのを見てどう思うかは人次第。。
しかしこれ、1文字の比較でこれである。文字数が増えれば当然増えていく。
↓単位はすべてns
collate | ‘1’ = ‘1’ | ‘1a’ = ‘1a’ | ‘yoku0825’ = ‘you0825’ | ‘🍣’ = ‘🍺’ |
utf8mb4_0900_ai_ci | 41.11 | 50.34 | 125.51 | 42.21 |
utf8mb4_general_ci | 23.73 | 26.84 | 54.08 | 26.46 |
utf8mb4_bin | 17.75 | 19.50 | 24.09 | 19.83 |
utf8mb4_0900_ja_as_cs | 22.47 | 129.95 | 432.00 | 50.89 |
latin1_swedish_ci | 17.56 | 21.64 | 30.02 | 24.20 |
たかだか8文字の比較で0.4usも持っていかれるのはなかなか…と見るか、それでもus単位だから十分じゃん? と見るか。
更に文字列の比較といえば ORDER BY
によるソートももちろん文字列の比較になるので、
mysql80 15> SHOW CREATE TABLE t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`num` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`aici` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL,
`generalci` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL,
`bin` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
`ja` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_ja_0900_as_cs DEFAULT NULL,
UNIQUE KEY `num` (`num`)
) ENGINE=InnoDB AUTO_INCREMENT=1000001 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
mysql80 15> SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.66 sec)
mysql80 15> SELECT * FROM t1 ORDER BY aici ASC LIMIT 1;
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
| num | aici | generalci | bin | ja
|
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
| 848775 | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d |
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
1 row in set (0.87 sec)
mysql80 15> SELECT * FROM t1 ORDER BY generalci ASC LIMIT 1;
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
| num | aici | generalci | bin | ja
|
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
| 848775 | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d |
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
1 row in set (0.96 sec)
mysql80 15> SELECT * FROM t1 ORDER BY bin ASC LIMIT 1;
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
| num | aici | generalci | bin | ja
|
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
| 848775 | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d |
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
1 row in set (0.92 sec)
mysql80 15> SELECT * FROM t1 ORDER BY ja ASC LIMIT 1;
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
| num | aici | generalci | bin | ja
|
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
| 848775 | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d | 0000104cd168386a335ba6bf6e32219d |
+--------+----------------------------------+----------------------------------+----------------------------------+----------------------------------+
1 row in set (1.74 sec)
100万行のクイックソートでこれくらい速度にも違いは出ますわな… utf8mb4_0900_ai_ci
はデフォルトだから意識されている気がするけど、 utf8mb4_ja_0900_as_cs
はやっぱりね…。
インデックスを作る時もやっぱりソートするので
mysql80 16> ALTER TABLE t1 ADD KEY (aici);
Query OK, 0 rows affected (6.05 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql80 16> ALTER TABLE t1 ADD KEY (generalci);
Query OK, 0 rows affected (5.44 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql80 16> ALTER TABLE t1 ADD KEY (bin);
Query OK, 0 rows affected (5.33 sec)
Records: 0 Duplicates: 0 Warnings: 0
mysql80 16> ALTER TABLE t1 ADD KEY (ja);
Query OK, 0 rows affected (6.89 sec)
Records: 0 Duplicates: 0 Warnings: 0
こっちはまあ誤差くらいかな…。
ご利用は計画的に。