IT-Q

一覧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 を使わないので、後ろのページでも速度が落ちません。

ここからどう深掘りされるか

この問いに答えられた場合、面談は次の質問に進みます。