GA

2018/12/13

utf8mb4_0900_ai_ci の速度をどう見るか

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

こっちはまあ誤差くらいかな…。

ご利用は計画的に。

0 件のコメント :

コメントを投稿