[STATUS: ONLINE] 当サイトは要約付きのエンジニア向けFeedです。

TechDistill.dev

[DISCLAIMER] 当サイトの要約は正確性を保証しません。気になる記事は必ず原文を確認してください。
cd ..

【要約】N+1 問題を、発行される SQL を数えて理解する [Zenn_Python] | Summary by TechDistill

> Source: Zenn_Python
Execute Primary Source

// Problem

開発者がORMを用いて関連データを取得する際、意図せず大量のSQLを発行するN+1問題に直面する。これは、関連データのアクセスが「遅延ロード」によって、ループ内での属性アクセス時に個別に発生するためである。


  • SQLの実行回数がデータ数 N に比例して増加する。
  • クエリ単体は軽量でも、DBとのネットワーク往復(RTT)が累積し、致命的な遅延を招く。
  • データ増に伴い性能が線形に悪化するため、開発環境では検知が困難である。

// Approach

著者は、N+1問題を「往復回数を定数に落とす」という観点から、以下の3つのアプローチで解決を図っている。


  • joinedload: JOINを用いて1回のクエリに集約する。多対一の取得に適している。
  • selectinload: 親の取得後に IN 句を用いて関連をまとめて取得する。一対多の取得に適している。
  • 集計関数の利用: 関連レコード自体が不要な場合は、JOINとGROUP BYを用いて集計のみを行う。

// Result

実測により、N+1発生時(101本)の157.4msに対し、joinedload(1本)は11.6ms、selectinload(2本)は12.6msと、劇的な改善を確認した。


  • selectinload は、複数のコレクションをJOINした際の行数増大(デカルト積)を防げる。
  • テストでクエリ数を制限することで、再発を防止する具体的な手法を提示した。

Senior Engineer Insight

> N+1は単なる遅延ではなく、Lambdaの課金増やAPIのレート制限、タイムアウトといった「機能停止」を招く。単に「クエリ1本にすること」を目的とせず、往復回数を定数化することに注力すべきだ。テストでクエリ数をアサートする手法は、大規模開発における防波堤として極めて有効である。

[ RELATED_KERNELS_DETECTED ]

cd ..

> System.About()

TechDistillは、膨大な技術記事から情報の真髄(Kernel)のみを抽出・提示します。