Accessの迷宮を突破せよ:Recordsetとトランザクションの「極限」最適化
Access VBAを「おもちゃ」と呼ぶ者は、その深淵を知らない。
何百万件ものレコードを裁くとき、`Recordset`の`.Edit`と`.Update`を漫然と繰り返すコードは、単なる低速化ではない。それはOSのリソースに対する冒涜であり、DBエンジン(ACE)への無知そのものだ。
今日は、中級者の壁を越え、システム全体のパフォーマンスを支配したいと願うエンジニアへ、トランザクションのスコープとオブジェクト管理の「極限の知見」を授ける。
—
1. なぜ「暗黙のコミット」は罪なのか
`Recordset.Update`を呼ぶたびにACEエンジンはディスクI/Oを発生させる。これをループ内で繰り返すことは、現代のSSD環境であってもI/O負荷の飽和を招く。
解決策は明確だ。トランザクションの意図的な制御である。`BeginTrans`と`CommitTrans`で物理的な書き込みタイミングを握りつぶせ。ただし、ここで注意すべきは「スコープ」だ。広すぎればロック競合でシステムが凍結し、狭すぎればオーバヘッドで窒息する。
最適化されたバッチ処理の構文
Public Sub HighPerformanceUpdate(ByVal targetTable As String)
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim ws As DAO.Workspace
Set db = CurrentDb
Set ws = DBEngine.Workspaces(0)
‘ Recordsetのタイプは必ずdbOpenDynasetかdbOpenTableを選択せよ
Set rs = db.OpenRecordset(targetTable, dbOpenDynaset, dbAppendOnly)
‘ トランザクション開始
ws.BeginTrans
On Error GoTo ErrHandler
Do While Not rs.EOF
rs.Edit
rs!ProcessedFlag = True
rs.Update
‘ バッチサイズを定義し、トランザクションを区切る(例:500件)
‘ これによりメモリ負荷とロック時間を最小化する
If rs.AbsolutePosition Mod 500 = 0 Then
ws.CommitTrans
ws.BeginTrans
End If
rs.MoveNext
Loop
ws.CommitTrans
Cleanup:
‘ オブジェクトの明示的解放はVBAにおける「礼儀」である
If Not rs Is Nothing Then rs.Close: Set rs = Nothing
Set db = Nothing
Exit Sub
ErrHandler:
ws.Rollback ‘ 失敗時は全ロールバックでデータ整合性を確保
Resume Cleanup
End Sub
—
2. メモリという名の戦場:オブジェクト解放の真実
VBAはガベージコレクションを信用してはならない。特に`CurrentDb`を安易に何度も呼び出すのは愚行だ。`CurrentDb`は呼び出すたびに新しいデータベースオブジェクトを生成し、メモリ上にスタックさせる。
- 鉄則1: `CurrentDb`は一度変数に代入し、再利用せよ。
- 鉄則2: `.Close`メソッドは、`Nothing`を代入する前に必ず実行せよ。
- 鉄則3: 循環参照を避け、プロシージャ終了時に必ずスコープを破壊せよ。
もし、これらを怠れば、Accessは「メモリリーク」という名の静かな死を迎える。
—
3. レガシー連携の極意:Windows APIの活用
外部CSVやAPI連携時、VBAのネイティブなファイルI/Oでは制御しきれない場合がある。そんな時は迷わず`kernel32.dll`を叩け。特に`GetTickCount`等を用いた処理時間の計測は、ボトルネックの可視化に不可欠だ。
‘ APIの宣言は標準モジュールのヘッダで静的に行う
Private Declare PtrSafe Function GetTickCount Lib “kernel32” () As Long
‘ 処理時間の計測用ラッパー
Public Sub MeasurePerformance(ByVal startTick As Long)
Dim endTick As Long
endTick = GetTickCount()
Debug.Print “経過時間: ” & (endTick – startTick) & ” ms”
End Sub
—
4. チーフアーキテクトからの忠告
Access VBAはレガシーではない。「究極のラピッドプロトタイピング環境」である。しかし、その力を引き出せるか否かは、エンジニアがいかに「ACEエンジンの呼吸」を理解しているかにかかっている。
1. ロックの粒度を意識せよ: テーブルロックを避け、ページロックを引き出せ。
2. インデックスを信じるな: `Recordset`を走査する際、インデックスが使われているか`ShowPlan`で確認する執念を持て。
3. 例外処理は聖域: トランザクション中のエラーは、常にロールバックを担保せよ。
現場で戦う諸君、システムは諸君が書くコードの「質」が全てだ。今日から、その一打一打に魂を込めろ。Accessは、まだ終わっていない。君たちが極限のコードを書く限り、それは最強の武器であり続ける。
