【実務・中級編】DAO.RecordsetのOpenRecordsetで指定する「dbOpenDynaset」と「dbOpenSnapshot」のメモリ消費比較 – Access VBA解析バイブル

スポンサーリンク

Access VBAを掌握する:DAO.Recordsetの「深淵」を覗く

Access開発において、`OpenRecordset`の選択を適当に行うことは、地雷原を裸足で歩くのと同じだ。

多くの開発者が「とりあえず動くから」とデフォルト設定でコードを書くが、それは将来的なメモリリークや、マルチユーザー環境でのロック競合という名の「時限爆弾」を仕込んでいるに等しい。今回は、DAOにおける `dbOpenDynaset` と `dbOpenSnapshot` の決定的な違いと、プロが選ぶべき「最適解」について解説する。

1. なぜ「Snapshot」が最強の選択肢なのか

読み取り専用でデータを参照する際、多くのエンジニアが `dbOpenDynaset` を使い続けている。だが、これは大きな間違いだ。

  • dbOpenDynaset(ダイナセット):
  • 役割: データの更新・削除が可能な双方向カーソル。
  • コスト: 常に元データとのライブリンクを維持し、レコードのロック管理や更新追跡のためのオーバーヘッドが発生する。
  • dbOpenSnapshot(スナップショット):
  • 役割: 抽出時点のデータの「静的なコピー」をメモリ内に構築する。
  • コスト: リンクを保持しないため、メモリ消費が極めて低く、更新の衝突(コンフリクト)を考慮する必要がない。

結論: 更新しないなら、絶対に `dbOpenSnapshot` を選べ。これだけで、ネットワークトラフィックの削減と、アプリケーションのメモリ肥大化を劇的に抑制できる。

2. 実務で「バグを生まない」ための実装パターン

ただコードを動かすだけでは不十分だ。Accessは、開いたレコードセットを適切に閉じてメモリを解放しないと、すぐにプロセスが死ぬ。

以下のコードは、大規模なデータ参照でもメモリ消費を最小限に抑える、実戦的なテンプレートだ。

‘ ———————————————————
‘ 関数名: GetCustomerData_Optimized
‘ 概要: メモリ効率を最優先したSnapshotでのデータ取得
‘ ———————————————————
Public Sub GetCustomerData_Optimized()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim strSQL As String

‘ CurrentDbをオブジェクト変数に格納(呼び出し回数を減らして最適化)
Set db = CurrentDb
strSQL = “SELECT CustomerID, CustomerName FROM T_Customers WHERE Active = True”

‘ 【重要】読み取り専用なら必ず dbOpenSnapshot を指定する
‘ dbReadOnly は、不用意な書き込みを防止する「保険」として必ずセットする
Set rs = db.OpenRecordset(strSQL, dbOpenSnapshot, dbReadOnly)

‘ レコードの有無を確認
If Not (rs.EOF And rs.BOF) Then
rs.MoveFirst
Do Until rs.EOF
‘ ここでビジネスロジックを実行
Debug.Print rs!CustomerName
rs.MoveNext
Loop
End If

‘ 【必須】解放プロセス
‘ オブジェクトの破棄は生成と逆の順序で行うのが鉄則
rs.Close
Set rs = Nothing
Set db = Nothing
End Sub

3. なぜこの設計が「堅牢」なのか

私がこのコードを「プロダクションレベル」と呼ぶのには、以下の理由がある。

1. `dbReadOnly` の明示:
`dbOpenSnapshot` を選んでいても、`dbReadOnly` を付与することで、コードミスによる誤書き込みをデータベースエンジンレベルでブロックできる。
2. `CurrentDb` のキャッシュ:
`CurrentDb` は呼び出すたびに内部で新規インスタンスが生成される可能性がある。変数に保持することで、メモリ管理の安定性とパフォーマンスを担保する。
3. 明示的なクローズ:
AccessのDAOは、ガベージコレクションに頼ってはいけない。`Set rs = Nothing` を忘れることは、メモリリークという名の「ゴミ」を溜め続ける行為だ。

開発現場のリーダーからの提言

君たちが作成しているシステムは、数年後には「レガシー」と呼ばれるかもしれない。その時、コードを読み返す未来の自分、あるいは後輩エンジニアが「なぜここでスナップショットを選んだのか」を理解できるコードを書くべきだ。

  • 更新が必要な場合のみ `dbOpenDynaset` を使う。
  • それ以外はすべて `dbOpenSnapshot` に倒す。

この単純なルールを徹底するだけで、君のアプリケーションのパフォーマンスは、他のエンジニアが書くコードより一段上の次元に達する。

「動くコード」ではなく、「壊れないコード」を書け。それが、真のプロフェッショナルの仕事だ。

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