【実務・中級編】Application.CurrentDbを直接参照してはいけない理由:DAO.Database変数のキャッシュによる高速化 – Access VBA解析バイブル

スポンサーリンク

【Access VBA極限考察】なぜあなたのコードは遅いのか?『CurrentDb』の呪縛を解く設計論

多くの開発者が、Access VBAでデータベースを操作する際、何の疑いもなく `CurrentDb.Execute` や `CurrentDb.OpenRecordset` を多用します。

「動いているから問題ない」? それは、あなたのコードが「Accessというエンジンの心臓部に無駄な負荷をかけ続けている」事実に気づいていないだけかもしれません。

今回は、業務自動化の現場で「なぜ `CurrentDb` を直接叩いてはいけないのか」というタブーを解き明かし、プロの現場で必須となるDAO.Databaseオブジェクトのキャッシュ戦略を授けます。

1. なぜ `CurrentDb` は「悪手」なのか

`CurrentDb` は、呼び出されるたびに新しい `DAO.Database` オブジェクトを生成し、システム内部でセッションの再構築に近い処理を行っています。

もし、1,000件のレコードをループ処理で更新する際、そのループ内で `CurrentDb` を毎回呼び出せば、1,000回のインスタンス生成とメモリ確保のオーバーヘッドが発生します。

  • 非効率な構造: インスタンス生成 → リソース確保 → 処理 → 破棄 → (次ループへ)
  • 弊害: 処理速度の劇的な低下、メモリリークのリスク、そして何より「データベース接続の不安定化」を招きます。

大規模なデータ処理や、複数のクエリを連続して発行するツールにおいて、この「塵も積もれば山となる」ロスは無視できません。

2. プロの設計:DAO.Database変数のキャッシュ化

この問題を解決する唯一の解法は、「モジュールレベル(またはクラスレベル)でデータベース接続を保持し、使い回す」ことです。

一度生成した `CurrentDb` を変数にキャッシュすることで、ループ処理のオーバーヘッドをゼロにし、メモリ消費を最小限に抑えます。

実践:プロダクションレベルのコードテンプレート

以下は、保守性と堅牢性を両立させた設計パターンです。

Option Compare Database
Option Explicit

‘ モジュールレベルで保持するDAO.Database変数
Private m_db As DAO.Database

‘ 初期化処理:データベース接続を一度だけキャッシュする
Private Property Get CurrentDB_Cached() As DAO.Database
If m_db Is Nothing Then
Set m_db = CurrentDb
End If
Set CurrentDB_Cached = m_db
End Property

‘ 終了処理:メモリを確実に解放する
Public Sub TerminateDatabase()
If Not m_db Is Nothing Then
Set m_db = Nothing
End If
End Sub

‘ 【実用例】大量更新処理のデモンストレーション
Public Sub BatchUpdateExample()
Dim rs As DAO.Recordset
Dim db As DAO.Database

‘ キャッシュした接続を取得
Set db = CurrentDB_Cached

‘ トランザクション処理を組み合わせることで更に高速化
db.BeginTrans
On Error GoTo Rollback_Error

Set rs = db.OpenRecordset(“SELECT FROM T_TargetTable”, dbOpenDynaset)

Do Until rs.EOF
rs.Edit
rs!ProcessedDate = Now()
rs.Update
rs.MoveNext
Loop

db.CommitTrans

rs.Close
Set rs = Nothing
Exit Sub

Rollback_Error:
db.Rollback
MsgBox “更新中にエラーが発生しました: ” & Err.Description, vbCritical
End Sub

3. 実務で「バグ」を生ませないための3つの鉄則

キャッシュ化を行う上で、必ず守らなければならない「鉄則」があります。

① 常に `Nothing` に戻す(明示的な解放)

Accessの終了時に自動でGC(ガベージコレクション)が働くのを期待してはいけません。特にフォームが閉じられる際や、プロシージャの終了時に `Set m_db = Nothing` を呼び出す習慣をつけてください。

② `BeginTrans` との組み合わせ

キャッシュしたデータベースオブジェクトを使う最大のメリットは、「DAOレベルのトランザクション」を制御しやすくなることです。`db.BeginTrans` を活用すれば、データ整合性を担保しつつ、ディスクI/Oを劇的に削減できます。

③ 外部ファイル接続との使い分け

もし `CurrentDb` 以外の外部mdb/accdbを操作する場合、`DBEngine.OpenDatabase` で取得したオブジェクトを同様にキャッシュしてください。決して「都度接続」を行わないこと。これがプロとアマチュアの決定的な違いです。

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

「動くコード」を書くのは簡単です。しかし、「負荷を理解し、計算資源を最適化したコード」を書くことこそが、エンジニアの付加価値です。

Access VBAはレガシーな言語だと揶揄されることもあります。しかし、その内部構造を掌握し、メモリとリソースを極限までチューニングしたあなたのツールは、どんな現代的な言語で書かれたコードにも負けない「最強の業務自動化エンジン」となるはずです。

さあ、今すぐあなたのコードにある `CurrentDb` の数を数えてみてください。そこが、あなたのエンジニアとしての進化のスタート地点です。

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