GraphQLのN+1問題
概要
GraphQLではN+1問題が発生しやすい
GraphQLのN+1問題は、リゾルバが個別にデータを取得することで発生する
単一で取得、関連作も取得、複数リソース含めて関連先も取得など様々な取得パターンがあり得るので事前に発行されるSQLを予測できない。従来のpreloadなどを使った静的なN+1の対処では無理。
原因
GpaphQLの階層的なデータ関係のリクエストに対してリゾルバは階層を一つ一つ解決するため
例
code:text
query {
users {
id
name
posts {
id
title
}
}
}
1. usersフィールドのリゾルバで全ユーザーを取得
SELECT * FROM users;
2. 各ユーザーごとにpostsフィールドのリゾルバが呼び出される
3. N+1回のSQLクエリが発行される
code:text
SELECT * FROM posts WHERE user_id = 1;
SELECT * FROM posts WHERE user_id = 2;
SELECT * FROM posts WHERE user_id = 3;
解決方法
DataLoaderの利用
複数のリゾルバのリクエストをバッチ処理でまとめる
例: 全ユーザーのpostsを1回のクエリで取得
code:text
SELECT * FROM posts WHERE user_id IN (1, 2, 3);
クエリの最適化
要はJoinする
リゾルバで事前に関連データをロードする
ORMの機能を活用
ActiveRecordのincludesやeager_loadを使用して関連データを事前に読み込む
/icons/hr.icon