カーソルは、大きなデータセットを処理する小さなイントラネットアプリケーションでページングするための妥当な選択ですが、タイムアウト後にそれらを破棄する準備をする必要があります。ユーザーは、放浪したり、昼食に行ったり、2週間の休日に行ったり、アプリケーションを実行したままにしたりするのが好きです。 Webベースのアプリの場合、「実行中」とは何か、ユーザーがまだ存在するかどうかをどのように判断するかという問題もあります。
これらは、クライアント数が多い大規模なアプリケーションや、WebベースのアプリやWebAPIのようにほぼランダムに出入りするクライアントには適していません。クライアント数がかなり少なく、リクエスト率が非常に高い場合を除いて、アプリケーションでカーソルを使用することはお勧めしません...その場合、行の小さなバッチを送信することは非常に非効率的であり、代わりに範囲リクエストなどを許可することを検討する必要があります。
カーソルにはいくつかのコストがかかります。カーソルがWITH HOLD
でない場合 トランザクションを開いたままにしておく必要があります。オープントランザクションは、autovacuumが適切に機能することを妨げ、テーブルの肥大化やその他の問題を引き起こす可能性があります。カーソルがWITH HOLD
と宣言されている場合 トランザクションが開いたままになっていない場合は、潜在的に大きな結果セットをマテリアライズして保存するためのコストを支払う必要があります。少なくとも、ホールドカーソルはこのように機能すると思います。代替案も同様に悪く、カーソルが破棄されるまでトランザクションを暗黙的に開いたままにし、行がクリーンアップされないようにします。
さらに、カーソルを使用している場合、接続を接続プールに戻すことはできません。クライアントごとに1つの接続が必要です。つまり、セッション状態を維持するだけでより多くのバックエンドリソースが使用され、カーソルベースのアプローチで処理できるクライアントの数に非常に現実的な上限が設定されます。
制限とオフセットを使用するステートレス接続プールアプローチと比較して、ステートフルなカーソルベースのセットアップを管理することの複雑さとオーバーヘッドもあります。タイムアウト後にアプリケーションでカーソルを期限切れにする必要があります。そうしないと、サーバー上で無制限のリソースが使用される可能性があります。また、どの接続にどのカーソルがあり、どの結果がどのユーザーに設定されているかを追跡する必要があります。...
一般に、それは非常に非効率的である可能性があるという事実にもかかわらず、LIMIT
およびOFFSET
より良い解決策になる可能性があります。多くの場合、OFFSET
を使用するよりも、主キーを検索する方がよい場合があります。 、しかし。
ちなみに、あなたはPL/pgSQLのカーソルのドキュメントを見ていました。このジョブには通常のSQLレベルのカーソルが必要です。
カーソルでデータベース接続を開いたままにする必要がありますか?
はい。
カーソルはトランザクション内で実行され、「閉じられる」までリソースをロックしますか?
WITH HOLD
でない限りはい 、その場合、他のデータベースリソースを消費します。
私が気付いていない他の「落とし穴」はありますか?
はい、上記で説明されているように。