MySQL5.7と8.0のパフォーマンスを比較検証してみましたー

MySQL 5.7と比べると、8.0の方が性能が良いという噂を簡単な検証で確認してみました。

結論としては、

  • 8.0の方がINSERTは早い
  • 8.0の方がSELECTも早いけど、正しくインデックス貼られていれば同程度
  • UPDATE、DELETEは同程度

という結果でしたー!

なお、サポート期限は以下のようになっています。

MySQLバージョンMySQLAWS RDSのMySQLAWS AuroraのMySQL
5.72023年10月31日2023 年 10 月2024 年 10 月 31 日

(Aurora バージョン2)

8.02026年4月30日未定未定

(Aurora バージョン3)

Amazon RDS での MySQL のバージョン - Amazon Relational Database Service
Amazon RDS for MySQL のバージョンについて学びます。
Amazon Aurora バージョン - Amazon Aurora
Amazon Aurora のバージョンについて説明します。バージョンには、それぞれのバージョン番号、リリースサイクル、バージョン廃止のタイムラインなどがあります。
スポンサーリンク

検証条件

  • 100万件と200万件のデータに対して、以下のパターンでCRUDの性能を検証
    • MySQL5.7インデックスなし
    • MySQL8.0インデックスなし
    • MySQL5.7インデックスあり
    • MySQL8.0インデックスあり

検証結果

100万件の検証結果

MySQL5.7

インデックスなし

MySQL8.0

インデックスなし

MySQL5.7

インデックスあり

MySQL8.0

インデックスあり

結果比較
100万件インサート51.69 sec47.43 sec58.13 sec57.23 sec8.0の方が若干早い

インデックスありだとインデックス構築分遅くなる

100万件カウント0.49 sec0.07 sec0.39 sec0.07 sec8.0の方が早い

インデックス貼った方が早い

1件SELECT0.56 sec0.54 sec0.02 sec0.00 sec8.0の方が若干早い

インデックス貼った方が早い

1件UPDATE0.77 sec0.76 sec0.01 sec0.01 secバージョンによる差はほとんどない

インデックス貼った方が早い

1件DELETE0.86 sec0.87 sec0.04 sec0.01 secバージョンによる差はほとんどない

インデックス貼った方が早い

200万件の検証結果

MySQL5.7

インデックスなし

MySQL8.0

インデックスなし

MySQL5.7

インデックスあり

MySQL8.0

インデックスあり

結果比較
200万件インサート1 min 42.67 sec1 min 36.24 sec1 min 55.69 sec1 min 53.43 sec8.0の方が若干早い

インデックスありだとインデックス構築分遅くなる

200万件カウント0.84 sec0.33 sec0.75 sec0.15 sec8.0の方が早い

インデックス貼った方が早い

1件SELECT1.74 sec1.04 sec0.02 sec0.00 sec8.0の方が若干早い

インデックス貼った方が早い

1件UPDATE1.68 sec1.69 sec0.02 sec0.00 secバージョンによる差はほとんどない

インデックス貼った方が早い

1件DELETE1.36 sec1.82 sec0.01 sec0.01 secバージョンによる差はほとんどない

インデックス貼った方が早い

 

検証環境

AWS Aurora

インスタンス:db.t3.medium

準備

テーブル作成

以下のテーブルを用意します。インデックスなしテーブルです。

create table user(
id INT,
type INT,
name VARCHAR(255)
);

テストデータ作成用のプロシージャ作成

テストデータはプロシージャーで作成します。

以下の通りデータ作成してくれるようになっています。

  • user.id:カウントアップ形式で数値を格納
  • user.type:カウントを2で割った余りを格納(あまり意味がないカラムです。)
  • user.name:「user_name_{カウント}」の値を格納

-- 区切り文字を「//」に変更する
DELIMITER //

-- make_sample_dataというテストデータ作成用プロシージャーを作成する

create procedure make_sample_data(in i int)
begin
  declare count int default 0;
  -- 繰り返し
  while count < i do
    set count = count + 1;
    INSERT INTO user VALUES(count, MOD(count,2),CONCAT('usr_name_',count));
  end while;
end
//
-- 区切り文字を「;」に戻す
DELIMITER ;

インデックスなし

MySQL 5.7検証

バージョン確認

select version();
+-----------+
| version() |
+-----------+
| 5.7.12 |
+-----------+
1 row in set (0.00 sec)

100万件のパフォーマンス検証

◾️100万件インサート

call make_sample_data(1000000);
Query OK, 1 row affected (51.69 sec)

◾️100万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.49 sec)

◾️1件SELECT

select * from user where id = 500000;

+--------+------+-----------------+
| id | type | name |
+--------+------+-----------------+
| 500000 | 0 | usr_name_500000 |
+--------+------+-----------------+
1 row in set (0.56 sec)

◾️1件UPDATE

update user set name = 'name_500001' where id = 500001;

Query OK, 1 row affected (0.77 sec)
Rows matched: 1 Changed: 1 Warnings: 0

◾️1件DELETE

delete from user where id = 500002;

Query OK, 1 row affected (0.86 sec)

200万件のパフォーマンス検証

テーブルを空にする

TRUNCATE TABLE user;

◾️200万件インサート

call make_sample_data(2000000);
Query OK, 1 row affected (1 min 42.67 sec)

◾️200万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
| 2000000 |
+----------+
1 row in set (0.84 sec)

◾️1件SELECT

select * from user where id = 1000000;

+---------+------+------------------+
| id | type | name |
+---------+------+------------------+
| 1000000 | 0 | usr_name_1000000 |
+---------+------+------------------+
1 row in set (1.74 sec)

◾️1件UPDATE

update user set name = 'name_1000001' where id = 1000001;

Query OK, 1 row affected (1.68 sec)
Rows matched: 1 Changed: 1 Warnings: 0

◾️1件DELETE

delete from user where id = 1000002;

Query OK, 1 row affected (1.36 sec)

 

MySQL 8.0検証

バージョン確認

select version();
+-----------+
| version() |
+-----------+
| 8.0.26 |
+-----------+
1 row in set (0.02 sec)

100万件のパフォーマンス検証

テーブルを空にする

TRUNCATE TABLE user;

◾️100万件インサート

call make_sample_data(1000000);
Query OK, 1 row affected (47.43 sec)

◾️100万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.07 sec)

◾️1件SELECT

select * from user where id = 500000;

+--------+------+-----------------+
| id | type | name |
+--------+------+-----------------+
| 500000 | 0 | usr_name_500000 |
+--------+------+-----------------+
1 row in set (0.54 sec)

◾️1件UPDATE

update user set name = 'name_500001' where id = 500001;

Query OK, 1 row affected (0.76 sec)
Rows matched: 1 Changed: 1 Warnings: 0

◾️1件DELETE

delete from user where id = 500002;

Query OK, 1 row affected (0.87 sec)

200万件のパフォーマンス検証

テーブルを空にする

TRUNCATE TABLE user;

◾️200万件インサート

call make_sample_data(2000000);
Query OK, 1 row affected (1 min 36.24 sec)

◾️200万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
| 2000000 |
+----------+
1 row in set (0.33 sec)

◾️1件SELECT

select * from user where id = 1000000;

+---------+------+------------------+
| id | type | name |
+---------+------+------------------+
| 1000000 | 0 | usr_name_1000000 |
+---------+------+------------------+
1 row in set (1.04 sec)

◾️1件UPDATE

update user set name = 'name_1000001' where id = 1000001;

Query OK, 1 row affected (1.69 sec)
Rows matched: 1 Changed: 1 Warnings: 0

◾️1件DELETE

delete from user where id = 1000002;

Query OK, 1 row affected (1.82 sec)

インデックスあり

user.idにインデックスをはる

alter table user add index id_index (id);

MySQL 5.7検証

100万件のパフォーマンス検証

テーブルを空にする

TRUNCATE TABLE user;

◾️100万件インサート

call make_sample_data(1000000);
Query OK, 1 row affected (58.13 sec)

◾️100万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.39 sec)

◾️1件SELECT

select * from user where id = 500000;

+--------+------+-----------------+
| id | type | name |
+--------+------+-----------------+
| 500000 | 0 | usr_name_500000 |
+--------+------+-----------------+
1 row in set (0.00 sec)

◾️1件UPDATE

update user set name = 'name_500001' where id = 500001;

Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

◾️1件DELETE

delete from user where id = 500002;

Query OK, 1 row affected (0.04 sec)

200万件のパフォーマンス検証

テーブルを空にする

TRUNCATE TABLE user;

◾️200万件インサート

call make_sample_data(2000000);
Query OK, 1 row affected (1 min 55.69 sec)

◾️200万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
| 2000000 |
+----------+
1 row in set (0.75 sec)

◾️1件SELECT

select * from user where id = 1000000;

+---------+------+------------------+
| id | type | name |
+---------+------+------------------+
| 1000000 | 0 | usr_name_1000000 |
+---------+------+------------------+
1 row in set (0.02 sec)

◾️1件UPDATE

update user set name = 'name_1000001' where id = 1000001;

Query OK, 1 row affected (0.02 sec)
Rows matched: 1 Changed: 1 Warnings: 0

◾️1件DELETE

delete from user where id = 1000002;

Query OK, 1 row affected (0.01 sec)

MySQL 8.0検証

100万件のパフォーマンス検証

テーブルを空にする

TRUNCATE TABLE user;

◾️100万件インサート

call make_sample_data(1000000);
Query OK, 1 row affected (57.23 sec)

◾️100万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
| 1000000 |
+----------+
1 row in set (0.07 sec)

◾️1件SELECT

select * from user where id = 500000;

+--------+------+-----------------+
| id | type | name |
+--------+------+-----------------+
| 500000 | 0 | usr_name_500000 |
+--------+------+-----------------+
1 row in set (0.00 sec)

◾️1件UPDATE

update user set name = 'name_500001' where id = 500001;

Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0

◾️1件DELETE

delete from user where id = 500002;

Query OK, 1 row affected (0.01 sec)

200万件のパフォーマンス検証

テーブルを空にする

TRUNCATE TABLE user;

◾️200万件インサート

call make_sample_data(2000000);
Query OK, 1 row affected (1 min 53.43 sec)

◾️200万件カウント

select count(*) from user;
+----------+
| count(*) |
+----------+
| 2000000 |
+----------+
1 row in set (0.15 sec)

◾️1件SELECT

select * from user where id = 1000000;

+---------+------+------------------+
| id | type | name |
+---------+------+------------------+
| 1000000 | 0 | usr_name_1000000 |
+---------+------+------------------+
1 row in set (0.00 sec)

◾️1件UPDATE

update user set name = 'name_1000001' where id = 1000001;

Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

◾️1件DELETE

delete from user where id = 1000002;

Query OK, 1 row affected (0.01 sec)
女性誌多数掲載!
普通の子に会える

まとめ

MySQL5.7と8.0のパフォーマンスを検証してみましたー!

結果としては

  • 8.0の方がINSERTは早い
  • 8.0の方がSELECTも早いけど、正しくインデックス貼られていれば同程度
  • UPDATE、DELETEは同程度

です!

UPDATEは更新カラムにインデックス貼られてるか否かで結果が変わってくるかもと思いますが、簡単な検証結果ということで!

MySQLのインデックスを貼ったカラムを更新するとインデックスサイズが肥大化するよ!という記事もありますので、よろしければ!

MySQLでインデックスを貼ったカラムを更新するとインデックスサイズが肥大化する
MySQLのインデックスを貼ったカラムを更新した場合のインデックスサイズとパフォーマンスへの影響を確認してみました。インデックスサイズは2倍以上増加し、SELECT・UPDATEのパフォーマンスは多少劣化するという結果となりました。