【実務・中級編】ADOのCursorLocationプロパティがパフォーマンスに与える影響:Client vs Server – Access VBA解析バイブル

スポンサーリンク

Access VBAの暗黒面を制御せよ:ADO CursorLocationが引き起こす「見えない地獄」の正体

現場で「Accessが重い」「ネットワークが詰まる」と嘆くエンジニアのコードを覗くと、決まってADOの接続設定が適当だ。特に`CursorLocation`の選択を「なんとなく」で行っているなら、君は自分の足元に時限爆弾を仕掛けているに等しい。

今日は、DAOの時代から一歩進み、ADOを駆使して堅牢な業務システムを構築する君のために、`adUseClient`と`adUseServer`の「境界線」を論理的に解説する。

—

1. そもそもCursorLocationとは何か?

ADOでレコードセットを開く際、`CursorLocation`は「誰がデータを管理し、どこで処理するか」を決定する司令塔だ。

  • `adUseServer`(サーバーサイドカーソル): データベースエンジン(SQL Server等)がカーソルを管理する。
  • `adUseClient`(クライアントサイドカーソル): データを一度ローカルメモリ(VBA実行環境)に引き抜いてから管理する。

多くのエンジニアが「サーバーがやってくれるなら`adUseServer`の方が速いだろう」と誤解する。だが、Access VBAにおいてその認識は致命的な設計ミスを招く。

—

2. なぜ「adUseClient」が正義なのか(実務的視点)

ネットワーク越しにSQL Server等へ接続する場合、`adUseServer`は「行単位」でサーバーと通信を行う。1000行のスクロールで1000回の往復が発生することを想像してほしい。ネットワークのレイテンシが君のアプリを殺す。

対して`adUseClient`は、「全データを一気にメモリへ転送(バルク転送)」する。

  • メリット: ネットワークの往復回数が激減し、ソートやフィルタリングをローカルCPUで爆速処理できる。
  • 代償: メモリ消費量が増大する。巨大なデータを安易に扱うとAccessが落ちる。

結論: 業務ツールにおいては、「必要な分だけ抽出条件を絞り込み、`adUseClient`でローカルメモリへ引き抜く」のが、最も堅牢かつパフォーマンスが高い構成だ。

—

3. 実装:保守性を担保したプロダクションコード

コピペで動くだけのコードはゴミだ。ここでは「コネクションの解放」と「エラーハンドリング」を徹底した、保守可能なテンプレートを提示する。

‘ ———————————————————
‘ 関数名: GetRecordsetClientSide
‘ 目的: SQLServerからクライアントカーソルでデータを安全に取得する
‘ ———————————————————
Public Function GetRecordsetClientSide(ByVal strSQL As String, ByVal connString As String) As ADODB.Recordset
Dim rs As ADODB.Recordset
Dim conn As ADODB.Connection

On Error GoTo ErrorHandler

Set conn = New ADODB.Connection
conn.ConnectionString = connString
conn.Open

Set rs = New ADODB.Recordset
‘ ここが極意:サーバーではなくクライアントで管理させる
rs.CursorLocation = adUseClient

‘ 切断型レコードセットを作成(接続を閉じてもデータは保持される)
rs.Open strSQL, conn, adOpenStatic, adLockReadOnly
Set rs.ActiveConnection = Nothing ‘ コネクションを切断してメモリ負荷を軽減

Set GetRecordsetClientSide = rs

‘ クリーンアップ
conn.Close
Set conn = Nothing
Exit Function

ErrorHandler:
MsgBox “データベース接続エラー: ” & Err.Description, vbCritical
If Not conn Is Nothing Then conn.Close
Set conn = Nothing
End Function

—

4. トランザクション処理の鉄則

`adUseClient`を選択した場合、トランザクション管理は接続(Connection)に対して行う必要がある。

注意すべきは、`adUseClient`で更新を行うと「バッチ更新」モードになりやすい点だ。`rs.UpdateBatch`を実行するまでサーバーに書き込まれない。この間、排他制御の責任は君のコードにある。

  • 鉄則: トランザクションは最小範囲で。
  • 鉄則: ネットワークエラーを想定し、必ず`RollbackTrans`をエラーハンドラに入れること。

—

5. チーフアーキテクトからの助言

「サーバーの負荷を下げたいから`adUseServer`を使う」という考え方は、Accessクライアントが主体となるシステムでは自己満足に過ぎない。

1. データ量が数万件を超えないなら: `adUseClient`一択。ローカル処理の安定性は圧倒的だ。
2. データ量が膨大なら: Accessに全データを渡すな。SQL Server側でViewを作成し、必要な結果セットだけを抽出せよ。
3. メモリ管理: `Set rs = Nothing` を忘れるのはプロ失格だ。オブジェクトのライフサイクルを意識せよ。

Accessは「ファイルベースのデータベース」と思われがちだが、ADOを正しく使えば、エンタープライズ級のフロントエンドに変貌する。「どこで、誰が、どう管理するか」。この問いを常に持ち続けることこそが、伝説のエンジニアへの第一歩だ。

健闘を祈る。何かあればまた聞きに来い。

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