データベースを使った開発について学んでいくと、「N+1問題」という言葉に出会うことがあります。処理が遅くなりやすい典型的な問題のひとつですが、名前だけでは何のことかイメージしづらいと感じる方もいるかもしれません。この記事では、N+1問題の意味や起こる仕組み、解決の考え方や関連する用語までを、初心者の方にもわかりやすいように整理して解説していきます。
N+1問題とは?
N+1問題とは、データベースから関連するデータを取り出す際に、必要以上にたくさんの問い合わせ(クエリ)を繰り返してしまい、処理が遅くなる問題のことです。たとえば、まず一覧をまとめて取り出し(これが1回)、その一覧の一件ごとに関連情報を別々に取り出す(これがN回)、という形でクエリが積み重なる様子から、合わせて「N+1」と呼ばれます。本来まとめて取れるはずのものを、細かく何度も取りに行ってしまうことで効率が悪くなる問題だと考えると分かりやすいでしょう。
N+1問題が重要な理由
データベースへの問い合わせは、一回ごとに少なからず時間がかかります。N+1問題が起きると、件数が増えるほど問い合わせの回数も増え、処理にかかる時間がどんどん長くなってしまいます。一覧に表示する件数が多いほど影響は大きくなり、サービスの動作が遅く感じられる原因になることがあります。こうした問題は、開発の段階では気づきにくく、データが増えてから表面化することもあります。性能を保つうえで、知っておきたい代表的な問題のひとつだと言えるでしょう。
N+1問題が使われる場面
N+1問題は、関連するデータを扱うさまざまな場面で起こり得ます。代表的な例としては、次のようなものが挙げられます。
- 一覧画面で、各項目に関連する情報を一件ずつ取り出している場面
- 記事の一覧とともに、それぞれの書き手の情報を別々に取り出す場面
- 表示する件数が多く、関連情報の取得が繰り返される場面
- データが増えてから、処理が急に遅く感じられるようになった場面
N+1問題の仕組み
N+1問題が起こる流れは、おおまかに次のように整理できます。
- まず、一覧となるデータをまとめて一回で取り出します
- 取り出した一件ごとに、関連する情報を別々に取りに行きます
- 件数がN件あれば、関連情報の取得もN回繰り返されます
- 最初の1回と合わせてN+1回の問い合わせとなり、処理が遅くなります
N+1問題と似た用語との違い
N+1問題とよく一緒に語られる言葉に「スロークエリー」があります。スロークエリーは一回の問い合わせ自体に時間がかかる問題を指すのに対し、N+1問題は一回ごとは速くても回数が多すぎることで遅くなる問題だと考えると整理しやすいでしょう。同じ「遅い」でも原因が異なります。N+1問題は、まとめて取り出す工夫によって問い合わせの回数を減らすことで改善できることが多い点も、押さえておくとよいでしょう。
N+1問題を理解するメリット
N+1問題の考え方を理解しておくと、データベースを使う処理がなぜ遅くなることがあるのか、その原因のひとつをイメージしやすくなります。これは、システムの開発に携わる人にとって特に役立つ知識ですが、性能の仕組みに関心がある人にとっても有用だと言えるでしょう。問い合わせの回数という視点を持っていれば、遅さの原因を探る際の手がかりになります。性能を意識した開発の力の基礎になる知識だと捉えると分かりやすいでしょう。
N+1問題の注意点
N+1問題は、開発しているときには件数が少なく、気づきにくいことがあります。データが増えてから初めて遅さが表面化することもあるため、関連するデータを繰り返し取り出していないかを意識することが大切です。改善する際は、関連情報をまとめて取り出す工夫などが用いられますが、やり方を誤ると別の問題につながることもあります。具体的な解決方法は利用する仕組みや環境によって異なるため、状況に応じて検討し、必要に応じて公式情報を確認すると安心でしょう。
N+1問題に関連する用語
N+1問題をより深く理解するために、あわせて知っておくと役立つ関連用語を紹介します。
- クエリ:データベースへの問い合わせや命令
- スロークエリー:処理に時間がかかってしまう問い合わせ
- JOIN:複数のテーブルを結合してデータを取り出す操作
- パフォーマンス:処理の速さや効率の度合い
- 実行計画:データベースが処理を行う手順の見取り図
まとめ
N+1問題は、関連するデータを取り出す際に問い合わせを必要以上に繰り返してしまい、処理が遅くなる問題です。一覧の取得が1回、その一件ごとの関連情報の取得がN回となることから、こう呼ばれます。件数が増えるほど影響が大きくなり、データが増えてから表面化することもあります。関連情報をまとめて取り出す工夫で改善できることが多い問題です。N+1問題を知っておくと、性能を意識した開発の理解につながるでしょう。
よくある質問
N+1問題はなぜそう呼ばれるのですか?
一覧をまとめて取り出す1回と、その一件ごとに関連情報を取り出すN回を合わせて、N+1回の問い合わせになることから、こう呼ばれます。問い合わせの回数が積み重なる様子を表した名前だと考えると分かりやすいでしょう。
N+1問題はどう改善できますか?
関連する情報を一件ずつ取り出すのではなく、まとめて取り出す工夫によって、問い合わせの回数を減らすことで改善できることが多いです。具体的な方法は利用する仕組みによって異なるため、状況に応じて検討するとよいでしょう。
N+1問題とスロークエリーは同じですか?
同じではありません。スロークエリーは一回の問い合わせ自体が遅い問題で、N+1問題は一回ごとは速くても回数が多すぎて遅くなる問題です。同じ遅さでも原因が異なると捉えると整理しやすいでしょう。

