【テクニカル・上級編】DAO.Indexオブジェクトでインデックスを動的に作成・削除する – Access VBA解析バイブル

スポンサーリンク

データベースの呼吸を制御せよ:DAO.Indexによる動的インデックス生成の極意

Accessにおけるパフォーマンスチューニングとは、突き詰めれば「I/Oの回数」と「メモリの汚染」をいかに殺すかという戦いに他ならない。特に、一時テーブルを多用する複雑な集計やクロスリファレンス処理において、検索用のインデックスを静的に定義しておくのは素人の所業だ。

今回は、DAOを用いて実行時にインデックスを動的に生成・破棄し、エンジンを極限まで加速させるための「禁断の技術」を伝授する。

なぜ「動的インデックス」なのか

通常、テーブル設計時にインデックスを固定するが、これは特定のクエリに対しては最適でも、一時テーブルを介した複雑な処理ではしばしばボトルネックとなる。

  • データ構造の柔軟性: 処理のフェーズごとに検索キーが異なる場合、静的なインデックスは不要なソートコストを生む。
  • 挿入負荷の軽減: 大量データを一気に流し込む際、インデックスが存在すると各レコードごとにB-treeの再構築が発生し、書き込み速度が著しく低下する。

真のアーキテクトは、「必要最小限のタイミングで作成し、不要になった瞬間に消し去る」というライフサイクル管理を徹底する。

DAOによる動的インデックス構築のアーキテクチャ

DAO(Data Access Objects)は古臭いと揶揄されることもあるが、Accessのローカルエンジン(ACE/Jet)と最も親和性が高く、APIを直接叩くよりも遥かにオーバーヘッドが小さい。

以下に、実戦でそのまま使用可能な、確実なオブジェクト解放を組み込んだモジュールを提示する。

‘ —————————————————————————–
‘ 目的: 指定テーブルに動的インデックスを作成し、処理後に即座に解放する
‘ —————————————————————————–
Public Sub CreateDynamicIndex(ByVal TableName As String, _
ByVal IndexName As String, _
ByVal FieldName As String, _
Optional ByVal IsUnique As Boolean = False)

Dim db As DAO.Database
Dim td As DAO.TableDef
Dim idx As DAO.Index
Dim fld As DAO.Field

‘ DAOの参照を明示的に取得(CurrentDbは呼び出しごとにインスタンスを生成するため注意)
Set db = CurrentDb
Set td = db.TableDefs(TableName)

‘ インデックスの重複防止チェック:既に存在する場合は削除して再構築(更新処理の定石)
On Error Resume Next
td.Indexes.Delete IndexName
On Error GoTo 0

‘ インデックスオブジェクトの作成
Set idx = td.CreateIndex(IndexName)
idx.Unique = IsUnique
idx.Primary = False

‘ フィールドの紐付け
Set fld = idx.CreateField(FieldName)
idx.Fields.Append fld

‘ テーブル定義への追加
td.Indexes.Append idx

‘ 明示的なオブジェクト解放(メモリの断片化を防ぐ)
Set fld = Nothing
Set idx = Nothing
Set td = Nothing
Set db = Nothing
End Sub

伝説的エンジニアが守る「鉄の掟」

このコードを現場で運用する際、以下の3点を徹底しなければシステムは遠からず破綻する。

1. CurrentDbの誤解を解く

`CurrentDb` は呼び出すたびに新たなDAO.Databaseオブジェクトを生成する。ループ内でこれを行うと、メモリリークの温床となり、最終的にAccessが「リソース不足」でクラッシュする。必ず変数に格納し、最後に解放せよ。

2. エラーハンドリングの先読み

インデックス生成はDDL(Data Definition Language)操作である。ロック競合が発生した際、`On Error Resume Next` で強引に握りつぶすのではなく、`Err.Number` を監視して、排他制御のタイムアウトをハンドリングするロジックを実装するのがシニアの流儀だ。

3. 実行順序の最適化

インデックスは「データの投入後」に作成せよ。空のテーブルにインデックスを貼るコストは微々たるものだが、数万件のレコードが入ったテーブルに対するDDL操作は、エンジンに多大な負荷をかける。

最終的な到達点:システム間連携への応用

この手法は、外部CSVをインポートして突合を行う際、極めて強力な武器となる。

1. WorkTableの作成(インデックスなし)
2. 大量データの高速INSERT(インデックスがないため爆速)
3. CreateDynamicIndexの実行(検索用インデックスを付与)
4. SQLクエリによる高速集計
5. テーブルの破棄またはインデックスの削除

このサイクルを回すだけで、数分かかっていたバッチ処理が数秒に短縮されることは珍しくない。

技術は「使えば良い」のではない。「制御してこそ」真価を発揮する。Accessという枯れた環境であっても、エンジニアの意志一つで、データベースの挙動は劇的に変貌する。この知見を、君の現場の「ボトルネック」解消に役立ててほしい。

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