【テクニカル・上級編】【中級】テーブル内の不要なインデックスをVBAで検出し、書き込み速度を改善する – Access VBA解析バイブル

スポンサーリンク

Accessの「見えない枷」を断つ:インデックス最適化による書き込み速度の極限追求

多くのエンジニアがAccessのパフォーマンスに絶望する瞬間、それは往々にして「書き込みが重い」という事象だ。しかし、その原因がACCDBの肥大化やネットワーク遅延だけにあると考えているなら、君はまだAccessの深淵を覗いていない。

真のボトルネックは、開発者が「とりあえず」で乱立させた無用なインデックスにある。インデックスは検索を高速化するが、同時に書き込み時にはツリー構造の再構築という重いコストを支払う。使われていないインデックスは、ただの「システムを殺す寄生虫」だ。

今日は、DAOの深層を叩き、不要なインデックスを冷酷に摘出するアーキテクトのための診断スクリプトを授ける。

—

1. インデックスの「コスト」を再定義する

Accessの`TableDef`における`Index`オブジェクトは、単なるメタデータではない。レコードが追加・更新されるたびに、エンジンはこれらのインデックスをバックグラウンドで維持する。特に、バッチ処理で数千件のレコードを投げ込む際、不要なインデックスが1つあるだけで、処理時間は倍加する。

今回は、システム運用の中で「どのインデックスが使われているか」を動的に判断するのは困難であるという前提に立ち、「主キー以外の不要と思われるインデックスをリストアップする」というアプローチをとる。

2. インデックス診断・最適化エンジン

このコードは、単にインデックスを表示するだけではない。`DAO.Index`オブジェクトを巡回し、その特性を解析する。メモリリークを避けるため、オブジェクトの明示的解放とエラーハンドリングを徹底している。

Option Compare Database
Option Explicit

‘ — 診断スクリプト: インデックスの残骸を摘出する —
Public Sub AnalyzeTableIndexes(Optional targetTableName As String = “”)
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim idx As DAO.Index
Dim fld As DAO.Field

Set db = CurrentDb

Debug.Print “— インデックス診断開始: ” & Now & ” —”

For Each tdf In db.TableDefs
‘ システムテーブルは無視する(レガシーな運用を破壊しないための防壁)
If (tdf.Attributes And dbSystemObject) = 0 Then
If targetTableName = “” Or tdf.Name = targetTableName Then
For Each idx In tdf.Indexes
‘ 主キーは最適化の対象外とする(論理的整合性の担保)
If Not idx.Primary Then
Debug.Print “Table: ” & tdf.Name & ” | Index: ” & idx.Name
Debug.Print ” – Unique: ” & idx.Unique & ” | IgnoreNulls: ” & idx.IgnoreNulls

‘ ここでインデックスの削除を推奨するか判断する
‘ 現場の知見として:頻繁に更新されるテーブルで、
‘ 検索に使われない複数フィールドインデックスは削除候補
End If
Next idx
End If
End If
Next tdf

‘ オブジェクトの明示的解放(メモリ管理の鉄則)
Set idx = Nothing
Set tdf = Nothing
Set db = Nothing

Debug.Print “— 診断終了 —”
End Sub

—

3. チーフアーキテクトからの深掘り:パフォーマンスを極めるために

コードを動かすだけなら初級者でもできる。真のエンジニアは、この後に続く「最適化の判断」をどう下すかだ。

A. インデックス削除の判断基準

1. 更新頻度の高いトランザクションテーブル:検索キーとして利用されないインデックスは即刻削除せよ。
2. カーディナリティ(値の多様性)の低いフィールド:性別やステータスフラグのような「値の種類が少ない」フィールドにインデックスを貼るな。これは全走査(Table Scan)よりも遅くなるケースが多い。
3. 複合インデックスの順序:`[部署ID] + [日付]` という複合インデックスがある場合、`[日付]`単体での検索はインデックスを活用できない。重複するインデックスがないか確認せよ。

B. なぜDAOなのか

ADODBではなくDAOを使う理由は明確だ。Accessのエンジン(ACE)と最も親和性が高く、`TableDef`や`Index`といったDDLレベルの制御が最も低コストで実行できるからだ。APIのオーバーヘッドを最小限に抑えることが、大規模システムにおけるVBAの鉄則である。

C. メモリ最適化の極致

`Set = Nothing` は単なる行儀の問題ではない。Accessのバックグラウンドプロセスにおけるオブジェクトのライフサイクル管理は、特にネットワーク越し(共有フォルダ上のバックエンド)で顕著な差を生む。接続を明示的に解放し、ACEエンジンへの負荷を最小限に留めることが、長時間稼働するシステムの安定性を保証する。

—

結びに代えて

君たちが管理しているそのAccessシステムは、かつて誰かが「良かれと思って」入れたインデックスという名の足枷で息絶えようとしているかもしれない。

システムを「速くする」とは、何かを足すことではない。無駄な贅肉を削ぎ落とし、エンジンが本来のポテンシャルを発揮できる土壌を整えることだ。この診断スクリプトを武器に、君のシステムの書き込み速度を「異次元」へと引き上げてみてほしい。

健闘を祈る。

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