【実務・中級編】SQLの実行計画を意識したQueryDefの書き方 – Access VBA解析バイブル

スポンサーリンク

Access VBAを掌握せよ:QueryDefで「実行計画」を支配する極限の最適化術

Access開発において、多くのエンジニアが犯す最大の過ちは「文字列連結でSQLを生成し、レコードセットを開いて放置する」という思考停止だ。

君たちが書いているそのコード、データベースのエンジンを泣かせていないか?

今日は、Access VBAにおける`QueryDef`を単なる「SQLの入れ物」から、データベースの性能を極限まで引き出す「強力な武器」へと進化させるための、プロフェッショナルな設計思想を伝授する。

—

1. なぜ「文字列連結」は死を招くのか

多くの初心者は、フォームの検索条件を`”SELECT FROM T_Sales WHERE CustomerID = ” & Me.txtID`のように組み立てる。これは二重の罪だ。

1. 実行計画の再利用が不可能: 毎回異なるSQLとして解釈されるため、Jet/ACEエンジンはキャッシュされた実行計画を使えず、その都度コンパイルコストを支払うことになる。
2. インデックスの不整合: 型の不一致や、クエリエンジンの最適化ルーチンが働かないケースが増え、フルテーブルスキャンを誘発する。

真のアーキテクトは「動的SQL」ではなく「パラメータークエリ」を定義する。 これこそが、データベースエンジンと対話するための唯一の正しい作法だ。

—

2. 賢者のQueryDef設計:パラメーターを固定せよ

QueryDefは、実行時に毎回SQLを書き換える場所ではない。一度定義し、パラメーターのみを差し替える。これが、インデックスを確実に効かせるための鉄則だ。

実装のベストプラクティス:プロダクションコード

以下のコードは、保守性と実行速度を両立させた「テンプレート」だ。これを君のプロジェクトの標準とせよ。

‘ ———————————————————
‘ @brief クエリを実行計画を意識したパラメーターで実行する
‘ @param strQueryName 保存済みQueryDef名
‘ @param dictParams パラメーター名と値の辞書
‘ ———————————————————
Public Sub ExecuteOptimizedQuery(ByVal strQueryName As String, ByRef dictParams As Object)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim prm As DAO.Parameter

Set db = CurrentDb
Set qdf = db.QueryDefs(strQueryName)

‘ パラメーターの値を注入
‘ QueryDef内で定義されたパラメータ名とDictのKeyを一致させること
For Each prm In qdf.Parameters
If dictParams.Exists(prm.Name) Then
prm.Value = dictParams(prm.Name)
End If
Next prm

‘ ここで実行。エンジンはコンパイル済み計画を即座に適用する
qdf.Execute dbFailOnError

Set qdf = Nothing
Set db = Nothing
End Sub

—

3. インデックスを殺すな:SQL最適化の「禁じ手」

QueryDefをいくら綺麗に書いても、SQLそのものがダメなら全てが無に帰す。以下の3つは、Access開発における「インデックス殺し」の代表格だ。

① 列に対する関数適用を避ける

`WHERE Year([SaleDate]) = 2023`
これは最悪だ。インデックスは`SaleDate`列そのものに貼られている。関数を通した瞬間にインデックスは無効化される。
改善案: `WHERE [SaleDate] BETWEEN #2023/01/01# AND #2023/12/31#` と書け。

② ワイルドカードの先頭指定を避ける

`LIKE “ABC”`
これはインデックスを無視して全件走査(フルテーブルスキャン)させる命令だ。
改善案: 検索範囲を絞り込める場合は、必ず前方一致(`LIKE “ABC”`)に設計を落とし込め。

③ 暗黙の型変換を排除せよ

文字列型と数値型の比較をSQLに混入させるな。Accessは気を利かせて変換してくれるが、その「気遣い」が数ミリ秒の命取りになる。パラメーター定義時に、必ず正しい型(`dbLong`, `dbText`など)を指定すること。

—

4. 現場のリーダーからの提言:クエリ定義のライフサイクル

Accessのファイルサイズ肥大化やパフォーマンス低下に悩む諸君へ。
「使わないクエリは即刻削除せよ」

アプリケーションのコード内にハードコーディングされたSQLが溢れている状態は、技術的負債の墓場だ。

  • 複雑な結合が必要な場合は、必ず「保存されたQueryDef」として保存する。
  • 実行計画は、そのクエリを一度開いて「実行」した瞬間に内部的にキャッシュされる。
  • VBA側では、その「名前」を呼ぶだけ。

この疎結合な設計が、数年後の君の保守作業を劇的に楽にする。

—

最後に:エンジニアとしての矜持

VBAは古臭い言語だと言われる。しかし、その裏で動くJETエンジン(ACE)は、数十年かけて熟成された極めて強力なクエリエンジンだ。

君たちが「なんとなく」書いているそのSQLを、最適化されたパラメータークエリへと書き換えるだけで、システムは劇的に軽快になるはずだ。

「動けばいい」はプロではない。「どう動くべきかを知って制御する」のがプロの仕事だ。
今日の知見を、明日からのコードに刻み込め。君の書くコードが、真の意味で効率的なシステムを作ることを期待している。

タイトルとURLをコピーしました