Webアプリケーションのパフォーマンス低下の原因としてよくあるのが スロークエリー(Slow Query) です。
特にデータ量が増えると、適切なDB設計をしていない場合 クエリの実行時間が極端に遅くなることがあります。
この記事では DB設計におけるスロークエリーの原因と対策について、実務でも使える改善方法をわかりやすく解説します。
スロークエリーとは#
スロークエリーとは、実行に時間がかかるSQLクエリのことを指します。
一般的には以下のような状態を指します。
- SQLの実行時間が長い
- データベースのCPU使用率が高い
- APIレスポンスが遅くなる
- データ量が増えると急激に遅くなる
スロークエリーは アプリケーションのパフォーマンス低下の大きな原因になります。
多くのデータベースでは、一定時間以上かかるクエリをスロークエリーとして記録できます。
例えばMySQLでは、以下の設定でスロークエリーをログに記録できます。
slow_query_log = 1
long_query_time = 2この場合、2秒以上かかったクエリがスロークエリーとして記録されます。
スロークエリーログを確認する#
MySQLではスロークエリーをログに記録できます。
SHOW VARIABLES LIKE 'slow_query_log';スロークエリーログを有効にすると、時間のかかるSQLを特定できます。
主な確認ポイント
- 実行時間
- 実行回数
- フルスキャンの有無
スロークエリーが発生する主な原因#
スロークエリーの原因は主に以下です。
- インデックス不足
- N+1問題
- 不適切なJOIN
- 大量データのフルスキャン
- 不適切なDB設計
これらを理解することで、パフォーマンス問題を事前に防ぐことができます。
インデックス設計を行う#
スロークエリー対策で 最も効果が高いのがインデックス設計です。
インデックスが無い場合、データベースは **テーブル全体をスキャン(フルスキャン)**します。
例
SELECT * FROM users WHERE email = '[email protected]';email にインデックスが無い場合、すべてのレコードを検索します。
インデックスを追加
CREATE INDEX idx_users_email ON users(email);これにより検索速度を大幅に改善できます。
複合インデックス#
複数カラムで検索する場合は複合インデックスを利用します。
CREATE INDEX idx_users_email_status
ON users(email, status);複数条件の検索では、単一インデックスより高速になることがあります。
LIMITで取得件数を制限する#
大量データを取得するとクエリが遅くなる原因になります。
SELECT * FROM logs;例
SELECT * FROM logs
ORDER BY created_at DESC
LIMIT 50;取得件数を制限することでレスポンスを改善できます。
キャッシュを活用する#
頻繁に実行されるクエリはキャッシュを活用すると改善できます。
例
- Redis
- Memcached
- アプリケーションキャッシュ
キャッシュを利用することで、DBアクセスを減らせます。
N+1問題を防ぐ#
ORMを使用している場合、N+1問題が発生することがあります。
例
SELECT * FROM users;
SELECT * FROM posts WHERE user_id = 1;
SELECT * FROM posts WHERE user_id = 2;
SELECT * FROM posts WHERE user_id = 3;ユーザー数分クエリが発行されるため、パフォーマンスが悪化します。
対策
SELECT users.*, posts.*
FROM users
JOIN posts ON users.id = posts.user_id;JOINを使用することでクエリ回数を減らせます。
SELECT * を避ける#
SELECT * は便利ですが、パフォーマンスに影響することがあります。
理由
- 不要なカラムまで取得する
- ネットワーク転送量が増える
改善例
SELECT id, name FROM users;必要なカラムだけ取得することで処理を軽くできます。
適切なJOIN設計#
JOINの設計が悪いとクエリが非常に遅くなります。
ポイント
- JOINカラムにインデックスを付ける
- 不要なJOINを減らす
- JOIN数を最小限にする
例
SELECT orders.id, users.name
FROM orders
JOIN users ON orders.user_id = users.id;orders.user_id にインデックスを付けることで高速化できます。
EXPLAINでクエリを分析する#
スロークエリーを改善するには クエリの実行計画を確認することが重要です。
EXPLAIN SELECT * FROM users WHERE email = '[email protected]';確認するポイント
- type
- key
- rows
- Extra
これにより フルスキャンが発生していないか確認できます。
DB設計で意識すべきポイント#
スロークエリーを防ぐためには DB設計の段階から意識することが重要です。
主なポイント
- 適切なインデックス設計
- 正規化されたテーブル構造
- JOIN回数を減らす設計
- 検索カラムの最適化
設計段階で対策しておくことで、大規模データでもパフォーマンスを維持できます。
よくあるスロークエリーのパターン#
フルテーブルスキャン#
インデックスが無い場合、すべてのデータを検索します。
type: ALLこれはパフォーマンス問題の典型例です。
ORDER BYでインデックス未使用#
SELECT * FROM users ORDER BY created_at;created_at にインデックスが無い場合、ソート処理が重くなります。
よくある質問#
スロークエリーの目安は?#
一般的には 1秒以上のクエリがスロークエリーとして扱われることが多いです。
インデックスを付けすぎるとどうなりますか?#
インデックスが増えると INSERT / UPDATE が遅くなる可能性があります。
まとめ#
スロークエリーは、Webアプリケーションのパフォーマンス低下の大きな原因になります。
主な対策は以下です。
- インデックス設計
- N+1問題の回避
- SELECT * を避ける
- JOIN最適化
- EXPLAINでクエリ分析
これらを意識することで、大規模データでも高速なDB処理を実現できます。











