【入門編】DAOとADOのトランザクション性能比較:ローカルテーブルvsリンクテーブルの速度検証 – Access VBA解析バイブル

スポンサーリンク
スポンサーリンク

DAO vs ADO:トランザクションの真実。リンクテーブルで「遅い」と嘆く前に知っておくべきアーキテクチャの正体

こんにちは。開発の現場へようこそ。
マクロの記録から一歩踏み出し、「VBAで本格的なシステムを作ってみたい」と考え始めたあなた。素晴らしい志ですね。

しかし、コードを書き進めていくうちに、こんな壁にぶつかることはありませんか?
「ロジックは正しいはずなのに、なぜか処理が異常に遅い……」
「リンクテーブルを更新すると、まるで時間が止まったかのように動かない……」

実はこれ、あなたのコードが悪いのではなく、「データの動かし方(アーキテクチャ)」の選択を間違えているだけかもしれません。

今日は、Access VBAにおける二大巨頭「DAO」と「ADO」。この二つの違い、そして「トランザクション」という強力な武器が、ローカルテーブルとリンクテーブル(SQL Serverなど)でどのように振る舞うのか。そのパフォーマンスの差を徹底検証していきます。

ここをクリアすれば、あなたは「ただコードが書ける人」から「システムの特性を理解して設計できるエンジニア」へと脱皮できますよ。さあ、一緒に見ていきましょう。

1. そもそも DAO と ADO は何が違うのか?

まず、この二つの正体を知っておきましょう。彼らはどちらも「データベースに命令を出すための道具(ライブラリ)」ですが、その設計思想が全く異なります。

DAO (Data Access Objects) :「Access専用の住人」

DAOは、Accessのエンジン(ACE/Jetエンジン)と最も親密な関係にあります。

  • 特徴: Access内部の構造を熟知している。
  • 得意技: Access内のローカルテーブルに対する操作。爆速です。
  • イメージ: 自宅の構造をすべて把握している、家の住人。

ADO (ActiveX Data Objects) :「多言語を操る旅人」

ADOは、Access以外(SQL Server, Oracle, Excelなど)とも会話ができる汎用的なツールです。

  • 特徴: OLE DBという共通言語を使って、外の世界とやり取りする。
  • 得意技: 外部データベース(サーバー)との通信。
  • イメージ: いろいろな国の言葉を話せる、優秀な外交官。

2. 「トランザクション」という守護神

検証に入る前に、「トランザクション」についておさらいしておきましょう。

例えば、銀行の振込処理を想像してください。
1. あなたの口座から1万円引く
2. 相手の口座に1万円足す

もし「1」が終わった直後に停電が起きたら? あなたの1万円は消えてしまいますよね。
これを防ぐのがトランザクションです。「一連の処理を『全部成功』か『全部なかったことにする』のどちらかに決める」という仕組みです。

  • Commit(コミット): 全て成功したので、確定させる!
  • Rollback(ロールバック): 途中でエラーが出たので、処理前の状態に戻す!

この「守りの処理」こそが、データの整合性を守るエンジニアの命綱なのです。

3. 【検証】パフォーマンス比較:どっちが速いのか?

では、いよいよ本番です。
「1,000件のデータを更新するトランザクション処理」を、以下の4つのパターンで行った場合の速度を検証してみましょう。

パターン 使用技術 対象テーブル 特徴
A DAO ローカル 最強のスピード。Accessの内部処理。
B DAO リンク リンク越しにDAOで命令を送る。
C ADO ローカル ローカルなのに「旅人」を使うので少し非効率。
D ADO リンク 外部通信を伴う。設定次第で重くなる。

検証用コード例

実際に、あなたがテスト環境で試せるコードを用意しました。これを参考に、自分の環境で速度を測ってみてください。

Option Compare Database
Option Explicit

' --- 準備:テスト用のテーブル(T_Test)を用意しておいてください ---
' フィールド: ID (Long), Val (Long)

Sub Benchmark_DAO_Local()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim i As Long
    Dim startTime As Double
    
    Set db = CurrentDb
    startTime = Timer
    
    On Error GoTo ErrorHandler
    
    ' トランザクション開始
    DBEngine.BeginTrans
    
    Set rs = db.OpenRecordset("T_Test", dbOpenDynaset)
    
    For i = 1 To 1000
        rs.AddNew
        rs!ID = i
        rs!Val = i
        rs.Update
    Next i
    
    ' 全て成功したら確定
    DBEngine.CommitTrans
    
    Debug.Print "DAO Local: " & Timer - startTime & " 秒"
    
CleanUp:
    rs.Close
    Set rs = Nothing
    Set db = Nothing
    Exit Sub

ErrorHandler:
    ' エラーが起きたら全て取り消す
    DBEngine.Rollback
    MsgBox "Error: " & Err.Description
    Resume CleanUp
End Sub

Sub Benchmark_ADO_Linked()
    ' ※要参照設定: Microsoft ActiveX Data Objects x.x Library
    Dim conn As ADODB.Connection
    Dim cmd As ADODB.Command
    Dim i As Long
    Dim startTime As Double
    
    Set conn = New ADODB.Connection
    ' 現在のデータベースに接続
    conn.Open CurrentProject.ConnectionString
    
    startTime = Timer
    
    On Error GoTo ErrorHandler
    
    ' ADOのトランザクション開始
    conn.BeginTrans
    
    For i = 1 To 1000
        ' SQL文で直接更新(リンクテーブルに対して実行)
        conn.Execute "INSERT INTO T_Test_Linked (ID, Val) VALUES (" & i & ", " & i & ")"
    Next i
    
    ' 確定
    conn.CommitTrans
    
    Debug.Print "ADO Linked: " & Timer - startTime & " 秒"
    
CleanUp:
    conn.Close
    Set conn = Nothing
    Exit Sub

ErrorHandler:
    ' エラー時はロールバック
    If Not conn Is Nothing Then conn.Rollback
    MsgBox "Error: " & Err.Description
    Resume CleanUp
End Sub

4. 衝撃の結果と、プロが教える「最適解」

検証の結果、一般的に以下のような傾向が現れます。

結果の傾向

1. DAO + ローカルテーブル (圧倒的1位)
Accessのエンジンが直接メモリ上で処理するため、これ以上ないほど速いです。
2. DAO + リンクテーブル (安定の2位)
リンク先のサーバーへ「命令」を送り、サーバー側で処理を完結させる動きが得意です。
3. ADO + リンクテーブル (要注意!)
ここが落とし穴です。ADOでリンクテーブルを扱う際、設定(CursorLocation)によっては、「サーバーからデータを一旦手元のPCに持ってきて、手元で計算して、また送り返す」という、ものすごく遠回りな動きをすることがあります。これが「遅い!」の正体です。

💡 エンジニアとしての最適解

では、私たちはどう使い分ければいいのでしょうか? 結論を言いますね。

# ① Access内のデータだけで完結する場合

迷わず「DAO」を使ってください。
ローカルテーブルへの操作において、ADOを使う理由はほとんどありません。DAOの方がシンプルで、高速で、Accessの作法に則っています。

# ② SQL Serverなどの外部サーバーとやり取りする場合

「ADO」または「パススルー・クエリ」を使いましょう。
ただし、リンクテーブルに対してVBAで1件ずつループして更新するのは厳禁です。

  • NG例: リンクテーブルを `Recordset` で開いて、`For` 文で1件ずつ `Update` する。

(これは、何度も往復便を出すようなもので、ネットワークが悲鳴を上げます)

  • OK例: `DoCmd.RunSQL` や `conn.Execute` を使い、「一括のSQL文(INSERT INTO… SELECT… 等)」としてサーバーに投げる。

(これは、大きな荷物を一度にトラックで送るようなもので、非常に効率的です)

最後に:一歩先へ進むあなたへ

「なぜ遅いのか?」を考えることは、コンピュータが裏側で何をしているのかを想像することです。

  • DAO は、家の中の最短ルートを知っている。
  • ADO は、外の世界とつながるための高度な通信手段。
  • トランザクション は、データの安全を守るための約束事。

これらを正しく組み合わせることができれば、あなたの作るシステムは、プロが作る「堅牢で高速なアプリケーション」へと進化します。

「マクロの記録」を卒業したあなたは、今、エンジニアとしての本当の旅を始めたばかりです。焦らず、一つ一つの動作の「意味」を噛み締めていってくださいね。

応援していますよ!

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