【入門編】QueryDefの実行時間を計測し、遅いクエリを特定する「パフォーマンスプロファイラ」の自作 – Access VBA解析バイブル

スポンサーリンク

Access VBAの深淵へ:動的クエリの「実行速度」を支配するプロファイラの作り方

こんにちは。現場で泥臭く、しかし誰よりも美しくコードを書くことを信条としているエンジニアです。

Accessを使っていて、「なんだか特定の処理だけ重いな」と感じたことはありませんか?その犯人は、たいてい「非効率なQueryDef(クエリ定義)」です。Accessのクエリはブラックボックスになりがちですが、我々プロは違います。「計測できないものは改善できない」。これが鉄則です。

今回は、Access内の全QueryDefの実行時間を自動計測し、遅い処理をあぶり出す「自作パフォーマンスプロファイラ」の設計図を授けます。これをマスターすれば、あなたはもう「なんとなく重い」という不安から解放されます。

—

なぜ「QueryDef」を直接操作するのか?

マクロや通常のDoCmd.OpenQueryを使っているうちは、処理の裏側で見えている「クエリの実行エンジン」を制御できません。`QueryDef`オブジェクトを使うと、「クエリの準備(コンパイル)」と「実行」を分離できます。

これが高速化の第一歩です。今回はこの仕組みを利用して、実行前後の時間を記録するラッパー(包み込む仕組み)を作ります。

—

ステップ1:計測ロジックの核を作る

まずは、時間を計測するクラスモジュール(または標準モジュール)の土台となる関数を準備します。ここでは、シンプルに経過時間をミリ秒単位で取得する手法を使います。

‘ 実行時間を計測し、ログを出力する汎用プロシージャ
Public Sub ExecuteAndProfile(queryName As String)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim startTime As Single
Dim endTime As Single
Dim threshold As Single

‘ 閾値:1秒(1000ミリ秒)以上かかったら警告する設定
threshold = 1.0

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

‘ 実行前の時刻を取得
startTime = Timer

‘ クエリの実行
qdf.Execute dbFailOnError

‘ 実行後の時刻を取得
endTime = Timer

‘ 経過時間が閾値を超えていたらイミディエイトウィンドウに警告
If (endTime – startTime) > threshold Then
Debug.Print “【警告】クエリ名: ” & queryName & ” が遅延しています。”
Debug.Print “実行時間: ” & Format(endTime – startTime, “0.000”) & ” 秒”
End If

Set qdf = Nothing
Set db = Nothing
End Sub

—

ステップ2:システム内の全QueryDefを自動スキャンする

次に、Access内に存在するすべてのクエリをループで回し、一斉にプロファイルする「監視官」のようなプロシージャを作ります。

Public Sub RunAllQueryProfiler()
Dim db As DAO.Database
Dim qdf As DAO.QueryDef

Set db = CurrentDb

‘ 全QueryDefをループ
For Each qdf In db.QueryDefs
‘ パラメータを含むクエリやシステムクエリを除外する処理が必要な場合も
If Left(qdf.Name, 1) <> “~” Then ‘ 一時クエリを除外
Debug.Print “計測中: ” & qdf.Name
ExecuteAndProfile qdf.Name
End If
Next qdf

MsgBox “全クエリのチェックが完了しました。”
End Sub

—

ここで陥りやすい「落とし穴」

初学者が必ず突き当たる壁が2つあります。ここをクリアすれば、あなたはAccess中級者の仲間入りです。

1. 「パラメータクエリ」の壁
`qdf.Execute`は、クエリがパラメータ(Forms![FormName]![ControlName]など)を必要とする場合、エラーを吐きます。本番環境で使う際は、`qdf.Parameters(“…”) = …` と値を代入してから実行するコードを追加する必要があります。
2. 「選択クエリ」の壁
`Execute`メソッドは「アクションクエリ(追加・更新・削除)」専用です。「選択クエリ」を計測したい場合は、`Recordset`を開く必要があります。

  • アクションクエリ: `qdf.Execute`
  • 選択クエリ: `Set rs = qdf.OpenRecordset` → `rs.MoveLast` で全行読み込み。

—

さあ、次はあなたの番です

このコードの素晴らしいところは、「自分の書いたコードが、実際にどれくらいのコストをかけているか」を肌感覚で理解できる点です。

  • 練習課題: まずは、特定の重いクエリを1つだけ指定して、このプロファイラを動かしてみてください。
  • 次のステップ: 実行時間をテーブル(ログ用テーブル)に書き出すように改造すれば、日付ごとのパフォーマンス推移グラフを作ることも可能です。

Access VBAは古い言語だと言われますが、「データベースの挙動を直接制御できる」という点において、これほど強力な武器はありません。

もしエラーが出ても、それはあなたが成長している証です。VBAのエラーメッセージは、システムからの「ここを修正してくれ」という優しきアドバイスだと思ってください。

さあ、コードを書いて、あなたのAccessを限界まで高速化しましょう!何か詰まったら、いつでも聞いてくださいね。応援しています。

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