私はさまざまな場所を調べましたが、パフォーマンス上の利点のためだけであっても、どこよりもPreparedStatement
優先されるべきであるという疑わしい主張をたくさん聞いてきました。s はバッチ処理されたステートメントのみに使用されるべきであり、それ以外には使用されるべきではないとStatement
主張しています。PreparedStatement
しかし、私がフォローしてきた (主にオンラインの) 議論には盲点があるようです。具体的なシナリオを提示しましょう。
DB接続プールを備えたEDA設計のアプリケーションがあります。イベントが発生すると、永続性が必要なものもあれば、そうでないものもあります。人為的に生成されたものもあります (たとえば、X 分ごとに何かを更新/リセットするなど)。一部のイベントは発生して順次処理されますが、他の種類のイベント (持続性も必要) は同時に処理できます (また処理される予定です)。
これらの人為的に生成されたイベントは別として、持続性を必要とするイベントがどのように到着するかについての構造はありません。
このアプリケーションはかなり前 (2005 年ごろ) に設計され、いくつかの DBMS をサポートしています。典型的なイベント ハンドラー (永続性が必要な場合):
- プールから接続を取得する
- SQL文を準備する
- 準備されたステートメントを実行する
- 結果セットを処理し、該当する場合は閉じます
- 準備されたステートメントを閉じる
- 必要に応じて別のステートメントを準備し、同じ方法で処理する
- 接続をプールに戻す
イベントにバッチ処理が必要な場合、ステートメントは一度準備され、addBatch
/executeBatch
メソッドが使用されます。これは明らかなパフォーマンス上の利点であり、これらのケースはこの質問には関係ありません。
最近、ステートメントを準備 (解析) し、それを 1 回実行してクローズするという全体的な考え方は、本質的に の誤用でありPreparedStatement
、サーバーまたはクライアントの準備済みステートメントが使用されているかどうかに関係なく、パフォーマンス上の利点はまったくないという意見を受け取りました。 (Oracle、DB2、MSSQL、MySQL、Derby など) は、そのようなステートメントを準備済みステートメント キャッシュにプロモートすることさえしません (少なくとも、デフォルトの JDBC ドライバー/データソースはプロモートしません)。
さらに、MySQL の開発環境で特定のシナリオをテストする必要がありましたが、Connector/J 使用状況アナライザーはこの考えに同意しているようです。バッチ化されていないすべての準備済みステートメントの場合、呼び出しは次のようにclose()
出力します。
PreparedStatement created, but used 1 or fewer times. It is more efficient to prepare statements once, and re-use them many times
前述のアプリケーション設計上の選択によりPreparedStatement
、接続プール内の各接続のすべてのイベントで使用されるすべての SQL ステートメントを保持するインスタンス キャッシュを持つことは、不適切な選択のように思えます。
誰かがこれについてさらに詳しく説明できますか? 「準備 - 実行 (1 回) - 閉じる」というロジックに欠陥があり、本質的に推奨されていませんか?
PS Connector/J に対してuseUsageAdvisor=true
andを明示的に指定し、 or のいずれかを使用すると、バッチ処理されていないすべての SQL ステートメントのインスタンスを呼び出すときに、効率に関する警告が表示されます。cachePrepStmts=true
useServerPrepStmts=true
useServerPrepStmts=false
close()
PreparedStatement