OracleとMySQLのプリペアドステートメント
ハードパース
SQLが初めて実行される
共有プールにキャッシュされていない場合
SQL分の構造変更
リソースを多く消費する解析プロセスとして説明されている
https://docs.oracle.com/en/database/oracle/oracle-database/23/tgsql/sql-processing.html
Parsingの部分→Hard Parseの場合、最適化などが行われる
https://docs.oracle.com/en/database/oracle/oracle-database/19/tgsql/img/cncpt250.gif
1. シンタックスチェック
2. セマンティックチェック
3. 共有プールチェック(ここで、ハードパースかソフトパースの分岐)
hard parse
The steps performed by the database to build a new executable version of application code.
データベースがアプリケーションコードの新しい実行可能バージョンを構築するために実行する手順。
The database must perform a hard parse instead of a soft parse if the parsed representation of a submitted statement does not exist in the shared SQL area.
データベースは、送信されたステートメントの解析済み表現が共有SQL領域に存在しない場合、ソフト解析ではなくハード解析を実行する必要があります。
table:oracle
機能 共有プール ステートメントキャッシュ
実装位置 DBサーバ側 DBクライアント側
内容 解析済み形式 実行可能なSQLステートメント
目的 パースオーバーヘッド削減 パースオーバーヘッド削減、クライアント側での効率化
table:oracle
機能 A: 解析済み形式 B: 実行可能なSQLステートメント
内容 パースオーバーヘッド削減、サーバ側の効率化 ネットワーク通信の削減、クライアント側の効率化
実装位置 DBサーバ側(SGA) DBクライアント側
SGA:System Global Area
A
生成される実行計画
中間形式のコード
SQL文の公文解析結果、最適化された実行計画、必要なリソース情報
B(jdbcドライバ)
実行可能なSQLステートメント
Bの場合だと、ステートメント識別子を送るらしい
DBサーバ側では、ステートメント識別子に対応した「解析済みのSQL」と紐づいており、それが共有プールの一部であるライブラリキャッシュなるものに保存されているとのこと
MySQL
https://dev.mysql.com/doc/refman/8.4/en/statement-caching.html
10.10.3 Caching of Prepared Statements and Stored Programs
For certain statements that a client might execute multiple times during a session, the server converts the statement to an internal structure and caches that structure to be used during execution.
クライアントがセッション中に複数回実行する可能性のある特定のステートメントについては、サーバーがそのステートメントを内部構造に変換し、実行時に使用されるようその構造をキャッシュします。
The server maintains caches for prepared statements and stored programs on a per-session basis.
サーバーは、セッションごとに準備されたステートメントとストアドプログラムのキャッシュを維持します。
Statements cached for one session are not accessible to other sessions.
あるセッション用にキャッシュされたステートメントは、他のセッションからはアクセスできません。
When a session ends, the server discards any statements cached for it.
セッションが終了すると、サーバーはそのセッション用にキャッシュされたステートメントを破棄します。
わかるのはMySQLはセッショ内のみでキャッシュ利用可能
jdbcドライバ側でもステートメントキャッシュはある
しかし、こちらもセッション毎に保存されている
※jdbc側のプリペアドステートメントキャッシュはデフォルトはOFF
https://dev.mysql.com/doc/connector-j/en/connector-j-connp-props-performance-extensions.html#cj-conn-prop_cachePrepStmts
mysql2 gemにはプリペアドステートメントキャッシュは無い
しかし、ActiveRecordには、1セッションにつき、max1000のステートメントをキャッシュする「StatementPool」なる機能がある
Rails 7.2以降では、mysql2アダプタでもprepared statementがデフォで有効化されるらしい
code:config/database.yml
default:
adapter: mysql2
prepared_statements: true/false
プリペアドステートメントキャッシュを有効化することでどれくらいのメモリが消費されるか?
jdbc
prepStmtCacheSize(default: 25個)
prepStmtCacheSqlLimit(default:256文字)
https://dev.mysql.com/doc/connector-j/en/connector-j-reference-configuration-properties.html
Table 6.13 Performance Extensions Properties
ActiveRecordでのStatementPoolでは、キャッシュする最大個数のみ設定が可能そう