QueryDefの「劣化」を許すな:Access VBAで実行計画を再構築する極限の技術
Accessにおける「遅延」の多くは、クエリ実行エンジンが過去の最適化を信じ込み、現在のデータセットに対して不適切な実行計画を固執し続けることに起因する。
特に、`QueryDef`オブジェクトは一度作成されると、そのSQLに対する実行計画がキャッシュされる。しかし、データ分布が劇的に変化するバッチ処理や、非定型なパラメーターが頻繁に注入される環境では、このキャッシュが「負の遺産」と化す。
本稿では、レガシーを掌握し、Accessのクエリエンジンを意のままに操るための「再コンパイル」と「メモリ管理」の真髄を記す。
—
なぜQueryDefは「鈍化」するのか
Access(Jet/ACEエンジン)のクエリ最適化エンジンは、非常に優秀だが「静的」な側面を持つ。`QueryDef`のSQLを書き換えて実行する際、エンジンが古い実行計画を保持したまま実行を試みると、インデックスの選択ミスや結合アルゴリズムの硬直化を招く。
これを解消する唯一無二の手段は、「QueryDefの実行計画を強制的にリセット(破棄・再生成)すること」である。
実践:QueryDefの再構築アーキテクチャ
単にSQLを書き換えるだけでは不十分だ。`QueryDef`のプロパティを操作し、オブジェクトの参照を適切に破棄・再生成することで、オプティマイザに「これは全く新しいクエリである」と再認識させる必要がある。
実行計画をリフレッシュするVBA実装
以下に、メモリの断片化を抑えつつ、確実に再コンパイルを促すための実装パターンを示す。
‘ —————————————————————————
‘ QueryDefを完全に再構築し、実行計画の再生成を強制するプロシージャ
‘ —————————————————————————
Public Sub ExecuteOptimizedQuery(ByVal queryName As String, ByVal sql As String)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Set db = CurrentDb
‘ 1. オブジェクトの明示的破棄(メモリリークの防止)
‘ 既存のQueryDefが存在する場合は削除し、キャッシュをクリアする
On Error Resume Next
db.QueryDefs.Delete queryName
On Error GoTo 0
‘ 2. 新規定義による強制再コンパイル
‘ クエリを再作成することで、エンジンは新しいSQLに対して実行計画を再評価する
Set qdf = db.CreateQueryDef(queryName, sql)
‘ 3. パラメーターの注入と実行
‘ ここでパラメータークエリとして明示的に型を指定することで、
‘ キャストによるオーバーヘッドを排除する
qdf.Parameters(0).Value = “TargetValue” ‘ 実際の型に合わせて適宜調整
qdf.Execute dbFailOnError
‘ 4. 後始末(重要:オブジェクトを解放し、即座にメモリをクリーンにする)
qdf.Close
Set qdf = Nothing
Set db = Nothing
‘ GCのタイミングを制御できないVBAでは、
‘ オブジェクトの参照を切ることが最大の「最適化」である
End Sub
シニアエンジニアが意識すべき「統計情報」と隠れた罠
Access/ACEエンジンにおいて、SQL Serverのような`UPDATE STATISTICS`コマンドは存在しない。しかし、以下の挙動を理解しておくことは、大規模システム保守において不可欠である。
1. インデックスの断片化: Accessファイル(.accdb)の肥大化は、インデックスの整合性を低下させる。`CompactDatabase`(最適化)をVBAから定期的に呼び出すことは、統計情報に準ずる「物理的な再構築」に他ならない。
2. パラメータスニッフィングの回避: `QueryDef`にパラメーターを渡す際、`Eval()`関数などを使ってSQL文字列に値を埋め込む手法は、実行計画の再利用性を著しく下げる。「パラメータークエリとして定義し、Parametersコレクションを通じて値を渡す」ことこそ、エンジンを正しく動かすための作法である。
3. Windows APIによるメモリ解放: 非常に重い処理を実行した後、Accessがメモリを解放しない場合は、`SetProcessWorkingSetSize` APIを呼び出し、ワーキングセットを明示的にクリアするテクニックも存在する。これは最終手段だが、長時間稼働するシステムでは極めて有効だ。
結論:システムは「生き物」である
コードを書くだけなら初心者でもできる。しかし、システムが時間の経過とともにどう変化し、エンジンがどう反応するかを予測し、コントロールするのが我々アーキテクトの仕事だ。
`QueryDef`の再構築は、単なるコード上のテクニックではない。「クエリエンジンと対話し、常に最適な状態へ導く」という、メンテナンスの哲学そのものである。
もしあなたのシステムで「以前は速かったのに」という声が聞こえたら、それはコードのせいではない。エンジンが「過去の亡霊」に囚われているだけだ。今すぐそのキャッシュを破壊し、新たな実行計画をその手に取り戻せ。
