【PHP/Laravel】Laravel パフォーマンス改善|DBインデックス設計入門

PHP / Laravel

Laravel でパフォーマンスを改善してくれる インデックス どんなものなのかな?

今回は、データベースの検索を速くするための仕組み である インデックス の基本から Laravel での設定方法 について、ご紹介します。

Laravel環境構築がまだの場合 は、下記より Laravel環境構築 を行なってください。

インデックス とは?

インデックス とは、データベースの検索処理を高速にするための仕組み のことです。

通常、インデックスが設定されていないカラム(項目)を検索する と、データベースはテーブル内のすべてのデータを1件ずつ確認 します。これを フルテーブルスキャン と呼びます。

データが少ないうちは問題ありません が、件数が増えるにつれて処理はどんどん遅くなり、目的のデータを見つけるまでに時間がかかるようになります

その問題を解決してくれる のが インデックス です。インデックス を設定することで、すべてのデータを順番に確認する必要がなくなり、目的のデータにすばやくアクセスできるようになります

イメージとしては 本の「索引(さくいん)」と同じ で、索引がない場合は最初のページから順番に探す必要がありますが、索引があれば目的のページにすぐたどり着くことができます

データベースのインデックスも、これと同じ役割を持っています

インデックス が設定されていない場合の処理(フルテーブルスキャン)とイメージ図

インデックス が設定されていない 場合、条件に一致するデータが見つかるまですべてのレコードを順番に確認していく必要があります(フルテーブルスキャン)

データが少ないうちは問題ありません が、件数が増えるにつれて検索にかかる時間が徐々に長くなっていきます

インデックス が設定されている場合の処理とイメージ図

インデックス が設定されている 場合、データベースはテーブル内のデータをすべて順番に確認するのではなく、インデックス を使って目的のデータに効率よくアクセスします
これにより、条件に一致するデータを素早く見つけることができ、検索処理の速度が大きく向上します

例えば、インデックス が設定されていない場合と同じように created_at を基準に並び替え(ORDER BY)してデータを取得する場合でも、インデックス を利用することで、あらかじめ整理された順序から効率よくデータにアクセスできる ため、すべてのレコードを取得して並び替える必要がなくなり無駄な処理を減らすことができます

インデックス が設定されていない場合のコード例 と実行される SQL

インデックス を設定する例 として、Postモデル(postsテーブル)Userモデル(usersテーブル) としているため、モデルやテーブル、ダミーデータなどまだ準備していない場合 は、下記を参考にご準備ください。

コード例

実行時間 の確認のため、簡易的に microtime関数を使って計測 し、「routes/web.php」に記述しています。

実行されるSQL

実際の実行時間

localhost/indexにアクセスする と、実行時間は更新するたびに変わりますが、平均で「0.003 秒」前後ぐらい になります

インデックス が設定されている場合のコード例 と実行される SQL

Laravel では、マイグレーションを使用してインデックスを追加することができます
既存のテーブルも、Schema::tableを使うことでインデックスを後から追加・削除することが可能 です。

インデックスの追加設定

Postモデル(postsテーブル)created_atインデックス を設定するために コマンド から マイグレーションファイルを作成

マイグレーション作成コマンド

マイグレーションファイルに created_at のインデックスを追加

マイグレーション の実行

実際の実行時間

localhost/indexにアクセスする と、実行時間は更新するたびに変わりますが、平均で「0.002 秒」前後ぐらいパフォーマンスが改善 されています
コード例実行されるSQL は、インデックスを設定していない場合 と同じものになります

複合インデックス が設定されていない場合のコード例 と実行される SQL

複合インデックス とは?

複合インデックス とは、2つ以上の複数のカラムを組み合わせて作るインデックス のことです。
複数条件での検索 や、絞り込みと並び替えを同時に行うクエリのパフォーマンスを改善すること ができます。

コード例

実行時間 の確認のため、簡易的に microtime関数 を使って計測 し、「routes/web.php」に記述しています

実行されるSQL

実際の実行時間

localhost/multiple-indexにアクセスする と、実行時間は更新するたびに変わりますが、平均で「 0.002 秒」前後ぐらい になります

複合インデックス が設定されている場合のコード例 と実行される SQL

インデックスの追加設定

Postモデル(postsテーブル)user_idcreated_at複合ンデックス を設定する ために コマンド から マイグレーションファイルを作成

マイグレーション作成コマンド

マイグレーションファイルに user_id と created_at のインデックスを追加

※ 通常、外部キー(例: user_id)を作成するとインデックスも自動的に作成 されます。
ただし、複合インデックスに外部キーが含まれる 場合、MySQLが複合インデックスを外部キー用に依存して利用してしまうことがある ため、外部キー用の単体インデックスを明示的に作成して依存関係を分離 させます。
外部キー(例: user_id)単体インデックスが設定されてある場合は追加されません

マイグレーション の実行

実際の実行時間

localhost/multiple-indexにアクセスする と、実行時間は更新するたびに変わりますが、平均で「 0.002 秒」前後ぐらい秒数的にはさほど変わらないですが少し改善されています
コード例実行されるSQL は、インデックスを設定していない場合 と同じものになります

単体インデックス と 複合インデックス の違い

単体インデックス は、created_at のように単一カラムでの並び替えや検索に効果があります
また 複合インデックス は、 user_id で絞り込みつつ created_at で並び替えるようなクエリに対して、より効率的に処理を行うこと ができます。

項目単体インデックス複合インデックス
対象1カラム複数カラム
得意な処理単一条件の検索・並び替え絞り込み + 並び替え
代表例created_atuser_id + created_at
効果的なSQLSELECT * FROM posts ORDER BY created_at DESCSELECT * FROM posts WHERE user_id = 100 ORDER BY created_at DESC

補足: 自動的にインデックスが付くケース

Laravel では、主キーUNIQUE制約 には多くのデータベースで自動的にインデックスが付与されます
ただ 外部キー については、データベースによって挙動が異なり、MySQLでは自動的にインデックスが作成されます が、PostgreSQLでは明示的にインデックスを追加する必要があります
timestamps(created_at, updated_at)には自動的にインデックスは付与されません

項目MySQLPostgreSQL補足
主キー✅ 自動で付く✅ 自動で付く一意識別のため必須
UNIQUE✅ 自動で付く✅ 自動で付く重複防止+検索高速化
外部キー✅ 自動で付く❌ 自動では付かないPostgreSQLは明示的に追加が必要

まとめ

今回は、データベースの検索処理を高速にするための仕組み である インデックス についてご紹介しましたが、いかがでしたでしょうか?

インデックス を設定することで、すべてのデータを順番に確認する必要がなくなり、目的のデータにすばやくアクセスできるようになります

また 複数のカラムを組み合わせて作成する 複合インデックス を活用することで、複数条件での検索 や、絞り込みと並び替えを同時に行うクエリのパフォーマンスをさらに改善することができます。

まずは、インデックス の基本的な仕組みを理解し、複合インデックス なども活用しながら、Laravel アプリケーションの パフォーマンス改善 に役立てていきましょう。

公式サイト

Laravel 12.x マイグレーション

12.x マイグレーション Laravel
tachu × tachu

Laravel / React フルスタックエンジニア

Webエンジニア歴15年、フリーランス歴8年で、PHP / Laravel を中心に、
React.js / Vue.js を用いたフルスタックでのWeb開発をしています。

技術記事は Laravel / React / Web開発 を中心に書いています。

Webサービスの開発、既存システム改善、機能追加、技術相談、小規模な開発など、お気軽にご相談ください。

PHP / Laravel
シェアする

コメント

タイトルとURLをコピーしました