【実務・中級編】Application.CurrentDbを毎回呼び出さない:DAO.Database変数のキャッシュによる処理速度改善 – Access VBA解析バイブル

スポンサーリンク

Access VBAの「目に見えないコスト」を削ぎ落とせ:CurrentDbキャッシュ戦略

Access VBAで業務アプリを構築する際、多くの開発者が無意識に犯している「静かなるパフォーマンスの殺人」がある。それが、ループ処理内での `CurrentDb` の安易な連発だ。

「とりあえず動くコード」を書く段階を卒業し、数万件のレコードを秒単位で処理するプロフェッショナルなツールを目指すなら、今すぐこの習慣を断ち切らなければならない。

なぜ `CurrentDb` をループで叩いてはいけないのか

初心者はよく、次のようなコードを書く。

‘ 【アンチパターン】絶対にやってはいけない書き方
For i = 1 To 10000
CurrentDb.Execute “UPDATE T_Sales SET Status = ‘Done’ WHERE ID = ” & i
Next i

一見、問題なさそうに見えるかもしれない。だが、Accessの裏側で何が起きているかを知れば、このコードがどれほど非効率か理解できるはずだ。

1. 毎回生成されるインスタンスの負荷

`CurrentDb` を呼び出すたびに、Accessは内部的に「現在のデータベースへの参照」を解決し、新しいDAO.Databaseオブジェクトを生成(あるいはキャッシュから再生成)するコストを支払っている。この微々たるオーバーヘッドが、ループの回数分だけ積もり積もれば、処理時間は指数関数的に増大する。

2. メモリのフラグメントとガベージコレクション

不必要なオブジェクト生成は、VBAのメモリ管理に余計な負荷をかける。特にバックエンドが重いネットワークドライブ上にある場合、この「無駄なアクセス」がネットワークトラフィックを無駄に占有し、システム全体の応答性を低下させる。

解決策:DAO.Database変数のキャッシュ

プロフェッショナルな設計において、データベースへの参照は「一度取得して、使い回す」のが鉄則だ。

推奨されるプロダクション・コード

以下は、堅牢性とパフォーマンスを両立させた実務向けの設計パターンである。

Public Sub UpdateSalesStatus()
‘ DAO.Databaseを保持するための変数を宣言
Dim db As DAO.Database
Dim i As Long

‘ 1. ループの直前で一度だけ参照を取得する
Set db = CurrentDb

‘ エラーハンドリングを組み込むことで、堅牢性を確保
On Error GoTo ErrorHandler

‘ 2. db変数を再利用して処理を実行
For i = 1 To 10000
‘ 毎回CurrentDbを呼ぶのではなく、キャッシュしたdbを使う
db.Execute “UPDATE T_Sales SET Status = ‘Done’ WHERE ID = ” & i, dbFailOnError
Next i

MsgBox “更新完了”, vbInformation

Cleanup:
‘ 3. 明示的に参照を解放(メモリリーク防止の儀式)
Set db = Nothing
Exit Sub

ErrorHandler:
MsgBox “エラー発生: ” & Err.Description, vbCritical
Resume Cleanup
End Sub

このコードが「プロ仕様」である理由

1. 参照のキャッシュ: `Set db = CurrentDb` をループの外に置くことで、オブジェクト生成コストを最小化した。
2. `dbFailOnError` の付与: 実行時にエラーが発生した場合、即座に例外をスローさせる。これにより、「更新できたつもり」のデータ不整合を防ぐ。
3. 明示的な解放: `Set db = Nothing` を `Cleanup` ラベルで行うことで、スコープ終了時の予期せぬメモリ保持を防ぐ。堅牢なシステムは、後始末までが美しい。

さらに上のステージへ:トランザクションの活用

もし君がさらに速度を求めるなら、単なる変数キャッシュだけでなく、「トランザクション」を組み合わせるべきだ。

`db.BeginTrans` と `db.CommitTrans` でループを囲めば、ディスクへの書き込み回数が劇的に減り、処理速度はさらに数倍〜数十倍に跳ね上がる。

db.BeginTrans
For i = 1 To 10000
db.Execute “…”, dbFailOnError
Next i
db.CommitTrans

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

「動けばいい」コードと、「長く、速く、壊れにくい」コードの間には、天と地ほどの差がある。

`CurrentDb` を毎回呼ぶことは、スーパーで買い物をするたびにいちいち家を出て財布を取りに帰るようなものだ。財布(データベース参照)を一度ポケットに入れれば、買い物の効率は劇的に変わる。

君が書くその数行のVBAが、誰かの業務時間を毎日数分ずつ短縮する。その責任と誇りを持って、今日からコードを改善してほしい。それが、世界最高峰の自動化エンジニアへの第一歩だ。

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