Wiz テックブログ

Wizは、最新のIoTやICTサービスをお客様に届ける「ITの総合商社」です。

MySQLで行うパフォーマンスチューニング

こんにちは。バックエンドエンジニアの米山です。

私個人はJava+Oracleでお仕事をする期間が長かったのですが、昔はよくOracle側のパフォーマンスチューニングを行っていました。
弊社では、まだ採用ケースは少ないのですがDBにMySQLを採用し、経年によるデータ増加に対応する場合にどうするべきか?を考えてみようと思います。

準備


まずデータ増加した(ということにする)DBを用意します。
本当は100万件・・・と言いたいところですが、時間がかかりそうなので10万件程度にしておきます。

以下のような構成で作成しました。

  • MySQLのバージョンは8(8.0.22)
  • テーブルを3つ用意する(samples,cities,join_data)
  • samplesにデータを10万件insertしておく(カラム数や中のデータは適当に散らばせる)
  • samplesにINDEXを作成(SAMPLES_IDX_01、SAMPLES_IDX_02)

今回は、データはLaravelのSeederを使って作成しました。

チューニングしてみる


準備ができたら、実行計画を取ります。
MySQLで実行計画を取る場合は「EXPLAIN」句を使います。
f:id:t-yone3:20210514180331p:plain

データ量が大したことないのですぐ返却されましたが(笑)テーブルのJOINはB(cities)->A(samples)->C(join_data)の順に結合されていること、Cへの結合はHASH JOINで行われていることなどがわかります。
INDEXもほど良く使われていますね。

Oracleではお馴染みのオプティマイザヒントですが、MySQLでも使えるようです。
試しにJOINの順番を変えてみましょう。
JOIN順番を指示するには「JOIN_ORDER」ヒントを指定します。 f:id:t-yone3:20210514180509p:plain

実行計画が変わったことが確認できました。

実務でよくあるのがINDEXヒントの導入です。
ビッグデータ且つデータの分布率が思わしくなく、INDEXを作成したのに有効に効かない時にクエリで指定してあげる、というケースが多いです。

MySQLでのINDEXヒントはOracleとは違い、FROM句の中で行います。 f:id:t-yone3:20210514180905p:plain

どうでしょうか?実行計画が変わったのがわかりますか?
USE INDEX(SAMPLES_IDX_02)を指定することで、意図的にそちらのINDEXを使用するようになりました。
但し、INDEXヒントはデータの状況や選択したINDEXによっては、逆にパフォーマンスを悪化させることもありますのでINDEXの選定と併せて、使用はご注意下さい。

最後にSQL実行時間の測定です。
実行計画を見ながら、実際にSQLが早くなったのかを確認していきます。
mysqlコマンドに-vvvオプションをつけて実行します。
f:id:t-yone3:20210514181035p:plain

今回紹介した、JOIN_ORDERとUSE INDEXを両方適用してSELECT文を実行しました。
本当に僅かですが実行時間が変わったことと思います。

プログラムコードを弄るほどではないけど、画面表示のパフォーマンスを改善したい!という時には効果的です。

最後に


Wizではエンジニアを募集しております。

興味のある方、ぜひご覧下さい。

【フロントエンドエンジニア】 場所にとらわれず自社メディア成長に貢献したいフロントエンドエンジニア募集! - 株式会社WizのWebエンジニアの求人 - Wantedly

【バックエンドエンジニア】 勤務地自宅を叶える!バックエンドエンジニアとして事業を成長させたい方募集 - 株式会社WizのWebエンジニアの求人 - Wantedly