web-dev-qa-db-ja.com

APIでページネーション用のカーソルを実装する方法

これは this question に似ていますが、答えはありません。 Twitterfacebook 、および disqus apiおよび この記事 でカーソルを使用する方法についてすべて読みました= disqusが一般的にどのようにカーソルを構築したかについてですが、私はそれらがどのように機能するか、および自分のプロジェクトに同様のソリューションを実装する方法の概念を理解することはできません。誰かがそれらの背後にあるさまざまな手法と概念を具体的に説明できますか?

42
Micah

offset paginationが大きなデータセットで失敗する理由を例を示して最初に理解しましょう。

クライアントは2つのパラメーター limit for the number of results and offset and for pageオフセット。たとえば、offset = 40、limit = 20の場合、最初の40をスキップして、次の20アイテムを返すようにデータベースに指示できます。

欠点:

  • LIMIT OFFSETの使用大規模なデータセットの場合、適切にスケーリングされません。オフセットがデータセット内で遠くに行くほど増加するので、オフセットを破棄してカウント行のみを返す前に、データベースは最大オフセット+ディスクからのカウント行を読み取る必要があります。
  • アイテムが高い頻度でデータセットに書き込まれている場合、ページウィンドウが信頼できなくなり、スキップしたり返されたりする可能性があります重複した結果

カーソルはこれをどのように解決しますか?

カーソルベースのページネーションはデータセット内の特定のアイテムへのポインターを返すによって機能します。後続のリクエストでは、サーバーは指定されたポインタの後に結果を返します。

パラメータ next_cursor limit とともにクライアントが提供するパラメータとして使用しますこの場合。

最新のユーザーから最も古いユーザーにページ番号を付けたいとしましょう。クライアントが初めてリクエストしたときに、クエリによって最初のページを選択するとします。

SELECT * FROM users
WHERE team_id = %team_id
ORDER BY id DESC
LIMIT %limit

ここで、 limit limit plus oneと等しく、クライアントによって指定されたカウントよりも1つ多い結果をフェッチします。追加の結果は結果セットでは返されませんが、値のIDを next_cursor として使用します。

サーバーからの応答は次のようになります。

{
   "users": [...],
   "next_cursor": "1234",  # the user id of the extra result
}

次に、クライアントはnext_cursorを2番目のリクエストのカーソルとして提供します。

SELECT * FROM users
WHERE team_id = %team_id
AND id <= %cursor
ORDER BY id DESC
LIMIT %limit

これにより、オフセットベースのページネーションの欠点に対処しました。

  • アイテムの総数に基づいて各リクエストのウィンドウをゼロから計算する代わりに、特定の参照ポイントの後で次のカウント行を常にフェッチします。アイテムが頻繁にデータセットに書き込まれている場合、セット内のカーソルの全体的な位置は変化する可能性がありますが、ページ付けウィンドウはそれに応じて調整されます。
  • これは、大規模なデータセットに対して適切にスケーリングされます。 WHERE句を使用して、前のページの最後のIDより小さいID値を持つ行をフェッチしています。これにより、列のインデックスを活用できますデータベースは、すでに見た行を読み取る必要がありません

詳細な説明については、 slack! からこの素晴らしいエンジニアリング記事をご覧ください。

53

一般に、現在のアイテムまたはページ番号をパラメーターとしてパラメーターに渡す必要があります。その他の通常のパラメーターは、ページのバッチサイズです。次に、サーバー側のバックエンドで、SQLクエリなどを使用して、適切なデータセットを選択して返します。

1
Ho Zong

ここにページネーションに関する記事があります: paginating-real-time-data-cursor-based-pagination

カーソル–カーソルベースのページ分割を実装するには、一意の連続値を持つ少なくとも1つの列が必要です。これは、Twitterのmax_idパラメータまたはFacebookのafterパラメータに似ています。

1
Goo Hong