一覧APIで paginate() を使ったら重くなりました。なぜですか。どうしますか。
総ページ数を出すために毎回 COUNT を別途発行するからです。数百万件規模ではこの COUNT 自体が重くなります。総件数の表示が要らなければ simplePaginate で消せます。
面接官が見ているのはページネーションの実装コストを知っているか。
これは「API のレスポンス設計として妥当なのはどれですか。」への追撃質問です。
よくある答えと、面談でどう見られるか
- 総ページ数を出すため毎回 COUNT が走るから。simplePaginate や cursorPaginate にする
その通りです。件数が数百万規模になると COUNT 自体が重くなります。cursorPaginate で速度優位を得るには order by 列にインデックスが必要な点まで言えると強いです。 - paginate() は全件を取得してから切り出しているから
LIMIT / OFFSET が付くので全件は取りません。重いのは COUNT の方です。 - OFFSET が大きいページほど遅くなるから
深いページでは実際にそうなりますが、1ページ目から重いなら COUNT が原因です。両方あるという理解が正確です。 - N+1 が起きているから
一覧APIでは併発しやすい問題ですが、paginate() 固有の重さは COUNT です。
面接官は何を見ているか
- 総件数を数える COUNT クエリが毎回走ると説明できた
- 件数が多いテーブルで COUNT が重いと指摘できた
- simplePaginate / cursorPaginate という選択肢を挙げた
模範解答
paginate() は総ページ数を出すために、毎回 COUNT クエリを別に発行します。件数が数百万規模になると、この COUNT 自体が重くなります。総件数の表示が要らないなら simplePaginate() にすれば COUNT が消えます。さらに深いページまで辿る場合は cursorPaginate() が有効で、OFFSET を使わないので、後ろのページでも速度が落ちません。
ここからどう深掘りされるか
この問いに答えられた場合、面談は次の質問に進みます。
観点をすべて押さえられた場合
cursorPaginate に変えると、できなくなることは何ですか。