Accessの深淵を覗く:CurrentDbの呪縛を解き、極限のパフォーマンスを引き出す設計術
Access VBAで開発を始めたエンジニアが、まず最初に覚えるのが `CurrentDb` だろう。しかし、その「便利さ」の裏側にあるコストを正確に理解している者は極めて少ない。
なぜ、大規模なデータ処理や多人数接続環境でAccessが失速するのか。その原因の多くは、無邪気な `CurrentDb` の乱用にある。今回は、伝説的なアーキテクトの視点から、DAOのライフサイクルを制御し、メモリ効率を極限まで高める設計パターンを伝授する。
—
1. CurrentDbの「正体」を理解せよ
`Application.CurrentDb` は、単なる関数ではない。呼び出されるたびに、Accessは内部的にデータベースオブジェクトの新しいインスタンスを生成している。
- オーバーヘッドの発生: 呼び出しのたびにリソースの確保とメモリ割り当てが行われる。
- 非効率なポインタ管理: 繰り返し呼び出すことは、メモリ上で「使い捨てのデータベース接続」を量産する行為に等しい。これは、ガベージコレクションが即座に働かないVBAにおいて、メモリリークやパフォーマンス低下の温床となる。
悪い設計例(アンチパターン)
‘ ループ内で毎回CurrentDbを呼ぶのは、パフォーマンスの自殺行為
For i = 1 To 10000
Set rs = CurrentDb.OpenRecordset(“SELECT FROM T_Master”)
‘ …処理…
rs.Close: Set rs = Nothing
Next i
このコードは、1万回のインスタンス化と破棄を繰り返す。CPUサイクルとメモリは確実に蝕まれる。
—
2. インスタンスのキャッシュ戦略
パフォーマンスを劇的に向上させるための鉄則は、「CurrentDbのライフサイクルを開発者が完全に管理する」ことだ。クラスモジュール、あるいは標準モジュールの静的変数(Static)にデータベースオブジェクトを格納し、アプリケーションのライフサイクルと同期させる。
ベストプラクティス:DBインスタンスのキャッシュ実装
‘ 標準モジュールにて実装
Private m_db As DAO.Database
Public Property Get CurrentDbCached() As DAO.Database
‘ 初回呼び出し時のみインスタンスを作成(シングルトンパターン)
If m_db Is Nothing Then
Set m_db = CurrentDb
End If
Set CurrentDbCached = m_db
End Property
‘ アプリケーション終了時に明示的に解放
Public Sub TerminateCache()
If Not m_db Is Nothing Then
m_db.Close
Set m_db = Nothing
End If
End Sub
この `CurrentDbCached` を利用することで、呼び出しコストを極小化できる。
—
3. メモリの解放と「Nothing」の義務
Access VBAにおいて、`Nothing` を代入することは「メモリ即時解放」を意味しない。しかし、「参照カウントを減らし、循環参照を回避する」という極めて重要な役目がある。
特に、`Database` オブジェクトや `Recordset` オブジェクトをモジュールレベルで保持する場合、以下の原則を厳守せよ。
1. スコープを限定する: 可能な限りプロシージャ内で完結させ、終了時に必ず `Nothing` を代入する。
2. イベント駆動の考慮: `Form_Unload` や `Application_Quit` で、保持しているすべてのDAOオブジェクトを明示的にクリアする設計を組み込む。
高度な設計:Windows APIによるメモリ監視
もし、本当に大規模なシステムを保守しているのであれば、`GlobalMemoryStatusEx` 等のAPIを呼び出し、自身のプロセスが消費している物理メモリを監視するユーティリティを組むべきだ。
‘ メモリ使用量を監視するAPI定義
Private Declare PtrSafe Sub GlobalMemoryStatusEx Lib “kernel32” (lpBuffer As MEMORYSTATUSEX)
‘ ※極限のチューニングを行う際、定点観測は必須である。
‘ なぜなら、Accessは「見えないメモリ」を溜め込みやすいからだ。
—
4. チーフアーキテクトからの提言:レガシーとの対峙
あなたが保守しているそのシステムが、もし10年以上前の設計であれば、`CurrentDb` の乱用が「データ破損」や「レコードロックの不整合」の引き金になっている可能性が高い。
- DAOからADOへの過信は禁物: 高速化のためにADOへ移行しようとするエンジニアがいるが、Accessのネイティブな制御にはDAOが最も相性が良い。DAOを極めずしてADOに逃げるのは、基礎を怠った者の逃避である。
- ネットワーク越しの処理: フロントエンドとバックエンドが分離されている場合、`CurrentDb` のキャッシュは、ネットワークトラフィックの削減にも直結する。
結論
`CurrentDb` は魔法ではない。単なる「入り口」に過ぎない。
その入り口を何度開閉しても良いのか、それとも一度開いて奥底まで使い倒すべきなのか――その判断こそが、エンジニアの腕の見せ所だ。
「コードは書くものではなく、設計するものである。」
今日から `CurrentDb` をキャッシュし、無駄なリソースの浪費を止めること。それが、あなたの書くAccessシステムの寿命を延ばす唯一の鍵だ。
