つまり、あなたの質問は最終的に「java.sql.PreparedStatement
」に要約されます。 最後に「これがサーバーで準備されたプランでどのように機能するか」に関する回答を参照してください。
答えは次のとおりです。これは、使用するJDBCドライバーによって異なります。
TL; DR :最新のドライバーでは、サーバーで準備されたステートメントは、接続が切断されるまで、またはステートメントが別のステートメントによって削除されるまで存続します(通常のLRU削除)。
注:PostgreSQLサーバーはデータベース接続間でプリペアドステートメントを共有できないため、JDBCドライバーが実行できる最善の方法は、各接続でプランをキャッシュしておくことです。
注:JDBC仕様では、?, ?
の使用が義務付けられています バインドプレースホルダーの場合、サーバーは$1, $2
を必要とします したがって、JDBCドライバーは、いわゆる解析済みSQLテキストもキャッシュします。
よく知られているJDBCドライバーには、pgjdbcとpgjdbc-ngの2つがあります
pgjdbc
https://github.com/pgjdbc/pgjdbc
pgjdbc9.4-1202
以降 PreparedStatement
を使用すると、サーバー側のプランが自動的にキャッシュされます。 注:close()
を実行しても、ステートメントはキャッシュされます。 PreparedStatement
。サーバー側の準備を行うには、クエリを5回実行する必要があります(prepareThreshold
で構成できます)。 。
現在、キャッシュは接続ごとに実装されています。デフォルトでは、pgjdbcは256をキャッシュします(preparedStatementCacheQueries
)クエリおよび最大preparedStatementCacheSizeMiB
クエリの。これは控えめな設定なので、調整することをお勧めします。 ドキュメント
を参照してください。 プロパティの説明については、キャッシュには解析済みステートメントとサーバー準備済みステートメントの両方が含まれます。
githubの問題: https://github.com/pgjdbc/pgjdbc/pull/319 >
pgjdbc-ng
https://github.com/impossibl/pgjdbc-ng
私はpgjdbc-ngに興味がありませんが、両方の解析を行っているようです(デフォルトのキャッシュサイズは 250 クエリ)およびサーバー準備(デフォルトのキャッシュサイズは 50 クエリ)。サーバー側のプリペアドステートメントのサポートは2014年2月24日に開始されたため、少し新しいバージョンを使用すると、ステートメントのキャッシュを取得できます。
注:誤って非常に長いクエリを使用した場合は、OutOfMemory
を押すことができます pgjdbc-ngは、保持されているバイト数に基づいてエントリを削除できないためです。
キャッシュは接続ごとであるため、ステートメントを閉じても透過的に使用されます。
pgjdbc-ngのパフォーマンスについてはあまり言えませんが、前回jmhをスローしようとして以来、ランダムな例外で失敗しました。
githubの問題: https://github.com/impossibl/pgjdbc-ng/pull/ 69
サーバーで準備された計画
PostgreSQLにはPREPARE
があります およびDEALLOCATE
EXEC
を送信するときにステートメントを参照するコマンド ワイヤー上。 2つのことを最適化します:
-
PREPARE
を使用する場合 dステートメント(つまり、サーバーで準備されたステートメント)の場合、クライアントはクエリテキストを何度も送信する必要はありません。短いクエリ名とバインド変数の値を送信するだけです。 - 9.2以降、データベースはクエリの最初の数回の実行を再計画しようとします。これは、クエリに複数のプランが必要な場合、または一般的なプランで十分かどうかを試すために行われます。最終的に(クエリにパラメータがない場合はすぐに)、データベース一般的なプランに切り替える可能性があります 。
- 12以降、サーバーで準備されたすべてのステートメントを汎用プランまたはカスタムプランで強制的に実行する設定があります。 plan_cache_mode
=
auto | force_custom_plan | force_generic_plan
つまり、PreparedStatement
JDBC側でのクエリ解析とデータベース側でのクエリプランニングの両方を最適化します。
詳細はこちら: http://blog.endpoint .com / 2014/04 / custom-plans-prepared-statements-in.html
PL/pgSQLで準備されたステートメント
ドキュメントによると、PostgreSQL キャッシュ> PL/pgSQLで使用されるクエリの計画。これは数回の実行(正確なしきい値を覚えていません)の後に発生するため、ストアドプロシージャを作成した後は少し遅くなる可能性がありますが、キャッシュされたプランに切り替わります(データベースが汎用プランの使用に同意した場合)特定のクエリの場合)。
つまり、「キャッシュされた実行プラン」を実現するには、最新のJDBCドライバーを使用するか、すべてのクエリをストアドプロシージャにラップする必要があります。プロシージャの呼び出しは実行ごとに再計画されますが、呼び出し自体は通常、プロシージャを構成するクエリよりもはるかに短いです。