26

重複の可能性:
API クライアントに 1,000,000 件のデータベース結果を提供する方法は?

Cursorsの使用について疑問に思うことは、PostgreSQL を使用して「ページング」を実装する良い方法です。

ユースケースは、API クライアントで利用できるようにしたい 100,000 行を超える場合です。これを実現する良い方法は、クライアントがバッチ (ページ) で情報を要求できるようにすることだと考えました。クライアントは一度に 100 行を要求できます。100 行とカーソルを返し、クライアントの準備が整うと、送信したカーソルを使用して次の 100 行を要求できます。

ただし、カーソルがどのように機能するか、およびカーソルをいつどのように使用する必要があるかについては、少しぼんやりしています。

  • カーソルでは、データベース接続を開いたままにする必要がありますか?
  • カーソルはトランザクション内で実行され、「クローズ」されるまでリソースをロックしますか?
  • 私が気付いていない他の「落とし穴」はありますか?
  • この状況を処理する別のより良い方法はありますか?

本当にありがとう!

4

2 に答える 2

37

カーソルは、大規模なデータ セットを処理する小規模なイントラネット アプリケーションのページングに適した選択肢ですが、タイムアウト後に破棄できるようにしておく必要があります。ユーザーは、うろうろしたり、ランチに行ったり、2 週間の休暇に出かけたりすることを好み、アプリケーションを実行したままにします。Web ベースのアプリの場合、「実行中」とは何か、ユーザーがまだ存在しているかどうかをどのように確認するかという問題さえあります。

Web ベースのアプリや Web API のように、クライアント数が多く、クライアントがほぼランダムに出入りする大規模なアプリケーションには適していません。クライアント数がかなり少なく、要求レートが非常に高い場合を除き、アプリケーションでカーソルを使用することはお勧めしません...その場合、行の小さなバッチを送信することは非常に非効率的であり、代わりに範囲要求などを許可することを検討する必要があります.

カーソルにはいくつかのコストがあります。カーソルがないWITH HOLD場合は、トランザクションを開いたままにしておく必要があります。トランザクションが開いていると、自動バキュームが適切に機能しなくなり、テーブルの肥大化やその他の問題が発生する可能性があります。カーソルが宣言さWITH HOLDれ、トランザクションが開いたままにされていない場合、潜在的に大きな結果セットを具体化して保存するコストを支払う必要があります-少なくとも、それがホールドカーソルの仕組みだと思います。代わりに、カーソルが破棄されるまでトランザクションを暗黙的に開いたままにし、行のクリーンアップを妨げます。

さらに、カーソルを使用している場合、接続を接続プールに戻すことはできません。クライアントごとに 1 つの接続が必要です。これは、セッション状態を維持するためにより多くのバックエンド リソースが使用されることを意味し、カーソルベースのアプローチで処理できるクライアント数に非常に実質的な上限を設定します。

また、制限とオフセットを使用したステートレスな接続プーリング アプローチと比較して、ステートフルなカーソル ベースのセットアップを管理する複雑さとオーバーヘッドもあります。タイムアウト後にアプリケーションのカーソルを期限切れにする必要があります。そうしないと、サーバー上で無限にリソースが使用される可能性があり、どの接続がどのユーザーに対してどの結果セットに対してどのカーソルを持っているかを追跡する必要があります....

一般に、それは非常に非効率的であるという事実にもかかわらず、より良い解決策になる可能性がLIMITあります. ただし、を使用するよりも主キーを検索する方がよい場合がよくあります。OFFSETOFFSET

ところで、あなたは PL/pgSQL のカーソルのドキュメントを見ていました。このジョブには通常の SQL レベルのカーソルが必要です。


カーソルでは、データベース接続を開いたままにする必要がありますか?

はい。

カーソルはトランザクション内で実行され、「クローズ」されるまでリソースをロックしますか?

WITH HOLD他のデータベース リソースを消費する場合を除き、はい。

私が気付いていない他の「落とし穴」はありますか?

はい、上記のとおりです。

于 2012-10-30T23:41:48.623 に答える
0

HTTPクライアントの場合、ページングを実装するためにカーソルを使用しないでください。スケーラビリティのために、サーバーリソースがリクエスト間で拘束されないようにする必要があります。

代わりに、クエリでLIMITとOFFSETを使用してください。Pgのドキュメントを参照LIMITOFFSETてください。

ただし、テーブルのインデックスがこの形式の効率的なクエリをサポートすることを確認してください。

クライアントが「next_url」(これも応答で渡される)を呼び出して次の行のセットを取得できるように、RESTfulAPIを設計します。

于 2012-10-30T16:00:31.457 に答える