『 1000件以上のリスト』は必ずページネーションが必要
大規模データを扱う API では適切なページネーション設計が UX とパフォーマンスを決めます。本記事では編集部の視点で、設計パターンを公開情報をもとに整理します。REST API 設計 もご参考に。
3つの主要パターン
(1) Offset Pagination:page/limit。(2) Cursor Pagination:next_cursor。(3) Keyset Pagination:where id > last_id。(4) Time-based:since/until。(5) 選び方:データ量と要件で。
Offset の特徴
(1) シンプル:?page=2&limit=20。(2) 任意のページへジャンプ可。(3) 欠点:大きいオフセットで遅い。(4) 欠点:データ追加で重複/欠落。(5) 小規模リストに向く。
Cursor の特徴
(1) 順次取得:next/prev。(2) 大規模データに強い。(3) データ変更に強い:重複防止。(4) 任意ページジャンプ不可。(5) SNS/タイムラインで標準。Relay 仕様(GraphQL)も Cursor。
Keyset の特徴
(1) WHERE id > ? ORDER BY id LIMIT n。(2) インデックス活用で超高速。(3) 10万件超のテーブルで威力。(4) 1方向のみ:戻り辛い。(5) tie-breaker:複数キーで一意化。SQL チューニング もご参考に。
実装例 (REST)
(1) GET /users?page=2&limit=20。(2) response: { data, total, has_next }。(3) Link ヘッダ:next/prev URL。(4) X-Total-Count:総件数。(5) maximum limitを設定。
GraphQL の Connection 仕様
(1) edges/node/cursor構造。(2) pageInfo: hasNextPage/endCursor。(3) Relay 仕様。(4) 標準的なフィルタリング。(5) 型安全。GraphQL 実践 もご参考に。
失敗しがちなパターン
(1) Offset で巨大データ:OFFSET 10000 で激遅。(2) limit 上限なし:DoS リスク。(3) total count を毎回計算:負荷大。(4) tie-breaker なし:Keyset で順序不安定。(5) キャッシュ困難:Cursor で。対策は、(1)Keyset/Cursor、(2)max=100、(3)approximate count、(4)id 併用、(5)key を含めたキャッシュキー、です。