【実務・中級編】Application.CurrentDbをキャッシュして処理速度を劇的に向上させる設計パターン – Access VBA解析バイブル

スポンサーリンク

Access VBAの「暗黙の罠」:CurrentDbを乱用するエンジニアは二流である

Access開発において、多くの初学者が陥る罠がある。それは、コードの至る所で`CurrentDb`を呼び出すことだ。

`Dim rs As DAO.Recordset`
`Set rs = CurrentDb.OpenRecordset(…)`

一見、何の問題もないように見えるこの記述。しかし、大規模なシステムや高頻度で実行されるループ処理において、この「何気ない一行」がシステムの喉元を締め上げるボトルネックになることを、君は知っているだろうか。

今回は、Accessのパフォーマンスを極限まで引き出し、かつ堅牢なアプリケーションを設計するための「CurrentDbキャッシュ戦略」を伝授する。

1. なぜCurrentDbを連呼してはいけないのか

`CurrentDb`は、単なるデータベースオブジェクトを返す関数ではない。呼び出されるたびに、内部で以下の処理が走っている。

1. 現在のデータベース接続の再評価:カレントDBのインスタンスを内部的に再生成(あるいは再参照)する。
2. オーバーヘッドの発生:オブジェクトの生成コストは、ミリ秒単位とはいえ、数千回・数万回のループ処理においては致命的な遅延となる。
3. リソースの断片化:不用意なインスタンス生成は、メモリリークのリスクを僅かながら増大させる。

「なんとなく動く」コードを書くのは素人だ。プロは、「一度生成したリソースは使い回す」という原則を徹底する。

2. 究極の設計パターン:モジュールレベルでのキャッシュ

最も効率的かつ安全な方法は、`CurrentDb`を保持するための専用のプロパティ(あるいは変数)を用意し、必要に応じてそれを参照することだ。

プロダクションコード例

‘ —————————————————————————
‘ モジュールレベルでDBインスタンスを保持する
‘ —————————————————————————
Private m_db As DAO.Database

‘ —————————————————————————
‘ DB取得用プロパティ(シングルトン風のアクセス)
‘ —————————————————————————
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 ProcessLargeData()
Dim rs As DAO.Recordset

‘ ここでCurrentDbを何度も呼ばず、キャッシュされたプロパティを利用する
Set rs = CurrentDB_Cached.OpenRecordset(“SELECT FROM T_Master”, dbOpenSnapshot)

‘ … 処理 …

rs.Close
Set rs = Nothing
End Sub

‘ —————————————————————————
‘ 終了処理:必ずNothingを明示的に代入してメモリを解放する
‘ —————————————————————————
Public Sub Terminate()
If Not m_db Is Nothing Then
Set m_db = Nothing
End If
End Sub

3. 実務における「落とし穴」と鉄則

この設計パターンを採用する上で、絶対に守らなければならない鉄則がある。

① データベースの「再接続」を考慮せよ

ネットワーク上の共有フォルダにあるバックエンドファイル(`.accdb`)を参照している場合、接続が切断されることがある。`m_db`がNothingではないのに接続が死んでいる、というケースだ。
シビアな環境では、`m_db`を保持し続けるのではなく、適切なタイミング(フォームのクローズ時や、一定時間経過後など)で明示的に解放し、再生成するロジックを組み込むべきだ。

② Nothing代入は「作法」ではなく「防壁」

VBAのガベージコレクションを信じてはいけない。特にDAOのオブジェクトやデータベース接続は、明示的に`Set m_db = Nothing`を行わないと、Accessのプロセス終了までメモリに残り続けることがある。
「生成したら必ず解放する」。この対になるコードを書く習慣がないエンジニアに、大規模開発を任せることはできない。

③ クラスモジュールを活用したカプセル化

小規模なツールなら標準モジュールでも良いが、中〜大規模開発なら`clsDatabase`のようなクラスを作成し、`Class_Terminate`イベントで自動的に解放処理を行うのが最も堅牢だ。

最後に:職人は道具の重みを知る

`CurrentDb`をキャッシュするという行為は、単なるコードの最適化ではない。「システムのリソースをどう管理するか」というアーキテクトとしての視点そのものだ。

Accessは非常に強力なツールだが、その分、書き手のスキルがダイレクトに速度と安定性に直結する。今回解説したキャッシュパターンは、君のアプリケーションを「一瞬で止まるツール」から「止まらない安定した業務基盤」へと進化させるはずだ。

次は、このキャッシュされたDBオブジェクトを用いて、いかにトランザクションを制御し、競合を回避するか。その知見を共有しよう。準備はいいか?

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