システム開発会社が運用するブログ TSTIPS ティーエスチップス システム開発会社が運用するブログ TSTIPS ティーエスチップス

[Laravel] N+1問題について

2021.12.23

Laravelにはモデルを扱うためのEloquentというORMがあります。おかげさまで、こまごましたコードを書かなくても、直感的にデータベースの操作を行うことができます。

しかし、よく切れるナイフをふるうにはそれなりの技術が必要です。

Laravelのもつポテンシャルを最大限に引き出すために、少しふみ込んで調査してみましょう。

今回は、知らなければついやってしまう「N+1問題」についてがテーマです。

N+1問題とは?

Laravelはサボり上手

Laravelには、効率よくデータを扱うためにLazyLoadという機能があります。

これは、データが必要になったときに、都度データベースにアクセスすることで、不要なデータを取得しないようにする機能です。

例えば、Userに紐づくPostモデルがあるとします。さらにPostには複数のCommentがつくとします。以下のようにUserのリレーションからすべてのPostを取得できますが、PostごとにあるCommentはViewで使用されていません。このとき、無用なCommentをわざわざデータベースから持ってくるのはめんどくさい!必要になったら取りいくわ!というのがLazyLoadです。

なかなか賢いですね。

怠惰の代償

しかし、Lazyであることによる失敗もあります。

先ほどの例で、PostのCommentを表示する場合、問題が発生します。

先を見越してCommentも取得しておけば、1度データベースにアクセスするだけで済みます。

Lazyであるがゆえに、無駄に多くデータベースに足を運ぶようになってしまいました。

Postsを取得するクエリ(1回) + PostごとのCommentを取得するクエリ(N回)が発行されることから「N+1問題」と呼ばれています。

データベースへのアクセスは、それなりの負荷がかかるため、Nが大きくなればなるほどパフォーマンスが下がってしまいます。レスポンスが遅くなれば、SEOでも不利になってしまいます。

対策

EagerLoadを使用することで、N+1問題を回避できます。Userを取得する際に、withを使うことで先にPostやCommentを取りに行っておきます。

気を付けないと、うっかりやってしまいそうです。

おせっかいで、なんでも先回りしてやってくれるLaravelですが、たまには失敗することもあります。きちんと理解してうまく扱ってあげましょう!

t.kusayanagi

この記事を書いた人

kusa

役職

Company運用会社

株式会社トランソニックソフトウェア

株式会社トランソニックソフトウェア

名古屋市でシステム開発・WEB制作を中心に事業を展開しています。システムに関すること、なんでもお気軽にご相談ください!

Search記事検索

開発パートナー募集中 システムエンジニア、WEBデザイナー積極採用