Access VBAの深淵:ADO CursorLocationが支配する「メモリ」と「ネットワーク」の最適解
Access開発において、DAOは標準的だが、外部DBやWeb APIとの疎通、あるいは大規模データ処理においてADO(ActiveX Data Objects)を避けて通ることはできない。しかし、多くのエンジニアが `CursorLocation` の設定をデフォルトのまま放置し、結果としてアプリケーションのパフォーマンスを腐敗させている。
本稿では、`adUseServer` と `adUseClient` の本質的な違いを、単なるマニュアルの引用ではなく、メモリ管理とトラフィック制御の視点から解剖する。
—
1. adUseServer:データベースサーバーへの「直結」
`adUseServer`(サーバー側カーソル)は、DBサーバーのリソースを最大限に活用する。
- 動作原理: レコードセットのポインタはサーバー上に置かれ、データは必要に応じてその都度フェッチされる。
- メリット:
- 初回応答速度: 全データを転送しないため、巨大なテーブルでも瞬時に開ける。
- リアルタイム性: 他のユーザーの変更が即座に反映される(ロック設定に依存)。
- 代償:
- 接続の占有: レコードセットを閉じない限り、サーバー上の接続(コネクション)を掴み続ける。
- ネットワーク負荷: ページ送りや検索を行うたびに通信が発生し、ネットワークのレイテンシ(遅延)に極端に弱い。
2. adUseClient:ローカルメモリへの「全権委譲」
一方で `adUseClient`(クライアント側カーソル)は、サーバー上のデータをごっそりとローカルメモリ上に引き抜く。
- 動作原理: `Recordset` が開かれた瞬間に全データをクライアント(Accessのプロセス内メモリ)へ転送し、以後の操作はメモリ上で完結する。
- メリット:
- 高度な機能: `Filter` や `Sort`、`Find` といったクライアントサイドの強力な機能が使用可能。
- ネットワーク解放: データ転送完了後は接続を閉じてしまっても、メモリ上のデータを操作できる。
- 代償:
- メモリ肥大化: 数百万レコードを読み込めば、Accessは容易にフリーズする。
- 初回読み込みの重さ: 全データが到達するまで処理がブロックされる。
—
3. 実践:最適化された接続とオブジェクト管理
レガシー環境で最も避けなければならないのは、メモリリークと接続の放置だ。以下のコードは、`adUseClient` を使用しつつ、リソースを極限までクリーンに保つアーキテクチャの雛形である。
‘ 伝説的なパフォーマンスを維持するためのADOハンドリング
Public Sub ExecuteOptimizedQuery(ByVal sql As String)
Dim conn As Object
Dim rs As Object
Set conn = CreateObject(“ADODB.Connection”)
Set rs = CreateObject(“ADODB.Recordset”)
‘ 接続設定:タイムアウトを制御し、ネットワークの異常を許容しない
conn.ConnectionTimeout = 15
conn.Open “Provider=SQLOLEDB;Data Source=ServerName;Initial Catalog=DBName;Integrated Security=SSPI;”
‘ クライアントカーソルでメモリ上に展開し、サーバー接続を最短で解放する
rs.CursorLocation = 3 ‘ 3 = adUseClient
rs.Open sql, conn, 3, 3 ‘ 3, 3 = adOpenStatic, adLockOptimistic
‘ 接続を切断しても、adUseClientならデータはメモリに存在する
Set rs.ActiveConnection = Nothing
conn.Close
‘ — ここでデータ加工を高速に行う —
‘ 終了処理:参照の明示的解放(オブジェクトのライフサイクルを制御)
If Not rs Is Nothing Then
If rs.State = 1 Then rs.Close
Set rs = Nothing
End If
Set conn = Nothing
End Sub
—
4. チーフアーキテクトからの提言:使い分けの指針
実務においてどちらを選択すべきか。判断基準は明確である。
1. adUseServerを選ぶべき時:
- 数万件以上のレコードを扱う場合。
- 頻繁に動的な検索(`WHERE`句の変更など)をサーバー側で行う必要がある場合。
- 同時実行性が高く、他者による更新を即座に感知したい場合。
2. adUseClientを選ぶべき時:
- レコード数が数千件以下で、メモリ上に収まる場合。
- ネットワーク環境が不安定な場合(接続を即座に切断できるため)。
- 複雑な並び替えや、VBA側で高度なデータ操作(フィルタリング等)を多用する場合。
最後に:Windows APIの活用について
もし大規模なデータ処理中にAccessがメモリを解放しない事象(いわゆるVBAのGCの弱さ)に直面した場合は、`SetProcessWorkingSetSize` APIを呼び出し、強制的に空きメモリをOSへ返還させる手法が有効だ。しかし、これは「対症療法」に過ぎない。
真のエンジニアは、`CursorLocation` を適切に設定し、不要な接続を `Nothing` にする。アーキテクチャを理解した上でコードを書くこと。それが、あなたのシステムをレガシーの呪縛から解放する唯一の道である。
