よろずやIT
プログラミング

N+1問題とは?原因と対策をORMの例でやさしく解説

執筆・監修:よろずやIT編集部|編集方針を見る

結論:まずここだけ読めばOK

詳しい手順・原因は、この下で解説しています。

プログラミングのイラスト

結論: N+1問題とは、1回で済むはずのデータ取得が、件数(N)に比例して何度も実行され、処理が遅くなる問題です。関連データをまとめて取得するよう書き換えると、改善できます。

N+1問題とは何か

N+1問題とは、データベースからデータを取得する際に、本来1回(または少数回)のクエリで済むはずの処理が、データの件数(N)に比例してクエリの回数が増えてしまう、パフォーマンス上の問題です。ORM(データベースの操作をプログラミング言語のコードとして扱えるようにする仕組み)を使った開発で、特に起こりやすいとされています。

具体的な例で理解する

「著者の一覧と、それぞれの著者が書いた本のタイトルを表示したい」という場面を考えてみましょう。

  1. まず、著者の一覧を取得するクエリが1回発行されます
  2. 次に、一覧の中の著者ごとに「この著者の本を取得する」というクエリが、著者の人数分(N回)発行されます

結果として、合計で「1 + N」回のクエリが発行されることになります。著者が10人なら11回で済みますが、10,000人いれば10,001回のクエリが発行され、データベースとの通信回数が膨れ上がり、処理が急激に遅くなります。

図で見る、クエリ回数の違い

問題が起きている状態と、解決した状態を、クエリの回数で比較してみましょう。

N+1問題によるクエリ回数の違いを示す図解

なぜ気づきにくいのか

N+1問題が厄介なのは、開発環境ではデータ件数が少ないため、体感できるほどの遅さにならないことが多い点です。テスト用のデータが数件〜数十件程度であれば、クエリが多少増えても目立った影響は出ません。しかし本番環境でデータが数千、数万件と増えた途端、突然「重い」と感じるようになります。この「開発環境では速いのに、本番では遅い」という症状の裏には、高い確率でN+1問題が潜んでいます。

解決策:Eager Loading(先読み)

N+1問題への基本的な対処法は、「Eager Loading(先読み)」と呼ばれる手法です。関連するデータを、ループが始まる前にまとめて取得しておくことで、クエリの発行回数を大幅に減らせます。

多くのORMには、この目的のための専用の仕組みが用意されています。例えばDjango公式ドキュメントでは、関連オブジェクトをまとめて取得するselect_related(結合によって1回のクエリで取得する方式)と、prefetch_related(関連ごとに個別のクエリを発行し、Python側で結びつける方式)という、2つの手法が説明されています。RailsやLaravelなど、他の主要なORMにも同様の仕組みが用意されています。

実際の開発現場でよくあるつまずき

日頃からできる予防策

まとめると

N+1問題は、ORMの手軽さの裏側にある代表的な落とし穴です。「関連データにアクセスするループを書いたら、まずEager Loadingを検討する」という意識を持っておくだけで、多くのケースを未然に防ぐことができます。

参考

※ 具体的な実装方法は使用しているORM・フレームワークによって異なるため、詳しくは各公式ドキュメントもあわせてご確認ください。

PR【中古】理論から学ぶデ-タベ-ス実践入門 リレ-ションモデルによる効率的なSQL/技術評論社/奥野幹也(単行本(ソフトカバー))

【中古】理論から学ぶデ-タベ-ス実践入門 リレ-ションモデルによる効率的なSQL/技術評論社/奥野幹也(単行本(ソフトカバー))

¥973

楽天で見る
SHAREXLINEはてブ

よくある質問

Q.N+1問題は、どんな時に特に発生しやすいですか?

A.一覧画面で、各項目に紐づく関連データ(著者ごとの本、投稿ごとのコメント数など)をループの中でその都度取得している場合に、特に発生しやすくなります。開発中はデータ件数が少ないため気づきにくく、本番環境でデータが増えてから初めて表面化することがよくあります。

Q.Eager Loadingを使えば、いつでも安心ですか?

A.多くの場合は改善しますが、万能ではありません。関連データの中でも特定の値だけが欲しい場合、Eager Loadingで全カラムを読み込んでしまうと、かえってメモリを圧迫することもあります。必要なデータの範囲を意識した使い分けが大切です。

Q.N+1問題が起きているかどうかは、どうやって確認できますか?

A.多くのORMには、開発時に発行されたSQLの本数を確認できるログ機能や、N+1を検知して警告してくれる仕組みが用意されています。処理に不自然に時間がかかっていると感じたら、まずは発行されているクエリの本数を確認してみることをおすすめします。

関連記事

最新のIT関連書籍 トップ10

PR / 楽天市場の売れ筋ランキングを定期的に取得しています。価格は変動する場合があるため、購入前に各ストアでご確認ください。