Access VBAを掌握する極限の知見:Unicode圧縮プロパティの動的制御によるDB極限サイズ最適化
長年、レガシーなクライアント/サーバー環境やローカル完結型システムの中枢として君臨してきたMicrosoft Access。その堅牢性は評価するにしても、現場のエンジニアを常に悩ませるのが「容赦なく肥大化するDBファイルサイズ(.accdb / .mdb)」の存在だ。
特に、テキストやメモといった文字列データを大量に扱うシステムでは、Jet/ACEデータベースエンジンのデフォルト挙動に足元をすくわれることが多い。その代表例が「Unicode圧縮(Unicode Compression)」の未徹底による容量の無駄遣いである。
今回は、Access VBAを駆使してテーブル定義の深層へ潜り込み、全フィールドのUnicode圧縮設定を強制的に最適化し、数ギガバイト規模の肥大化したデータベースを極限までスリム化するチーフアーキテクト流のノウハウを公開する。
—
1. なぜUnicode圧縮を見直す必要があるのか?
Accessの `Text` 型(短テキスト)フィールドは、内部的にUTF-16(1文字あたり2バイト)で文字列を保持する。
ここで発生するのが、英数字や半角カタカナといった「本来1バイトで表現できる文字」までもが2バイトとして格納されるという致命的な冗長性だ。
Accessには、これを自動的に1バイトに圧縮して格納する「Unicode圧縮」というプロパティが存在する。GUI上ではテーブルデザイナの各フィールドプロパティから設定可能だが、以下の致命的な問題がある。
- デフォルトの気まぐれ: 新規フィールド作成時、Accessのバージョンや作成方法によってこのプロパティが有効になったり無効になったりする。
- 既存データの放置: すでに数百万件のレコードが詰まったテーブルに対して、手動でポチポチと設定を変更していくのはエンジニアの労力の無駄遣いであり、ヒューマンエラーの温床となる。
この課題をVBAによるメタデータ操作(DAO)で完全に制御下置き、一網打尽に最適化するのが本稿の目的である。
—
2. アーキテクチャ上の注意点:DAOとADOの使い分け
Accessのテーブル定義(TableDef)やフィールド定義(Field)を操作する場合、ADO(ActiveX Data Objects)ではなく、DAO(Data Access Objects)を使用しなければならない。
ADOはデータ操作(DML)やスキーマの汎用的な取得には優れているが、Access固有の深いプロパティ(UnicodeCompressionなど)を書き換える能力を持たない。DAOこそが、ACEエンジンと直接対話できる唯一の特権的なAPIであることを忘れてはならない。
また、システム開発の現場において、オブジェクトの明示的な解放(`Set … = Nothing`)を怠ることは、メモリリークやJetエンジンのロック解放遅延を引き起こす悪しき習慣である。極限のパフォーマンスを求めるコードでは、リソースのライフサイクルを完全に掌握せよ。
—
3. 実装コード:全テーブル・全テキストフィールド一括最適化モジュール
以下のVBAコードは、カレントデータベース内のすべてのユーザーテーブルを走査し、`Text` 型(`dbText`)を持つフィールドの `UnicodeCompression` プロパティを強制的に `True`(有効)に書き換えるプロシージャである。
Option Compare Database
Option Explicit
‘ =========================================================================
‘ módulo名: modDbOptimizer
‘ 概要 : データベース内の全テーブルにおけるテキスト型フィールドの
‘ Unicode圧縮を強制有効化し、ファイルサイズを極限まで削減する
‘ =========================================================================
Public Sub OptimizeUnicodeCompression()
Dim dbs As DAO.Database
Dim tdf As DAO.TableDef
Dim fld As DAO.Field
Dim startTime As Double
Dim processedTables As Long
Dim processedFields As Long
startTime = Timer
Set dbs = CurrentDb
‘ エラーハンドリングの要塞化
On Error GoTo ErrorHandler
Debug.Print “=== Unicode圧縮の最適化プロセスを開始 ===”
‘ トランザクションはスキーマ変更には効かないため、TableDefsを直接操作
For Each tdf In dbs.TableDefs
‘ システムテーブル(MSysで始まる)およびリンクテーブルを除外
If (tdf.Attributes & dbSystemObject) = 0 And (tdf.Attributes & dbAttachedTable) = 0 Then
processedTables = processedTables + 1
For Each fld In tdf.Fields
‘ 対象は Text型 (dbText) のみ。Memo(dbMemo/LongText)型は圧縮アルゴリズムが異なるため除外
If fld.Type = dbText Then
‘ すでにTrueの場合は書き込みオーバーヘッドを避けるため条件分岐
If fld.UnicodeCompression = False Then
‘ プロパティの書き換えを実行
fld.UnicodeCompression = True
processedFields = processedFields + 1
Debug.Print ” [更新] テーブル: ” & tdf.Name & ” / フィールド: ” & fld.Name
End If
End If
Next fld
End If
Next tdf
Debug.Print “=== プロセス完了 ===”
Debug.Print “処理テーブル数: ” & processedTables
Debug.Print “圧縮有効化フィールド数: ” & processedFields
Debug.Print “所要時間: ” & Format(Timer – startTime, “0.00秒”)
‘ データベースの最適化(CompactRepair)を促すメッセージ
MsgBox “Unicode圧縮の設定変更が完了しました。” & vbCrLf & _
“変更を物理的なファイルサイズに反映させるため、” & vbCrLf & _
“必ず「データベースの最適化(Compact)」を実行してください。”, vbInformation, “最適化完了”
CleanUp:
‘ オブジェクトの明示的解放(メモリリークの完全防止)
On Error Resume Next
Set fld = Nothing
Set tdf = Nothing
Set dbs = Nothing
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“Error: ” & Err.Number & ” – ” & Err.Description, vbCritical, “致命的エラー”
Resume CleanUp
End Sub
—
4. コードの深層解説:なぜこの実装なのか
1. システムテーブルとリンクテーブルの厳格な除外
`tdf.Attributes` をビット演算で評価し、`dbSystemObject`(`MSysObjects` など)や `dbAttachedTable`(SQL Serverや別Accessへのリンク)を確実に弾いている。システムテーブルに手を出すとデータベースが破損する。リンクテーブルのプロパティをローカル側で書き換えようとしてもエラーになるため、このガードは必須である。
2. `dbText` と `dbMemo`(LongText)の分離
Access 2010以降の「長いテキスト(LongText / dbMemo)」型は、内部的にUTF-8に近いストレージ構造や別管理を行っており、従来の `UnicodeCompression` プロパティの制御対象外、あるいは挙動が異なる。予期せぬエラーを防ぐため、明示的に `fld.Type = dbText` のみに絞り込んでいる。
3. 「変更の反映」における最大の罠(重要)
VBAで `fld.UnicodeCompression = True` に設定しても、Accessの物理的なファイルサイズは一瞬で小さくならない。
Access(Jet/ACEエンジン)は、データを削除したり圧縮設定を変更して空き領域が生まれたとしても、それを「再利用可能な内部領域」として保持し続ける仕様(ファイルのデフラグメンテーション未実施状態)だからだ。
したがって、このVBAを実行した後に、必ず 「データベースの最適化(Compact and Repair Database)」 を手動、または `DBEngine.CompactDatabase` メソッドを用いてプログラム側から実行し初めて、数ギガバイト単位のサイズ削減が完了する。
—
5. チーフアーキテクトからの実務的提言
このスクリプトを定期バッチやデプロイ時の初期化ルーチンに組み込むことで、野良アプリと化したAccessデータベースの肥大化を根本から断つことができる。
特に、外部システムからCSVやAPI経由で半角英数字のマスターデータを大量にインポートするような設計のシステムでは、このチューニングを行うだけでファイルサイズが 30%〜50%以上削減 されるケースも珍しくない。
技術の本質を見極め、フレームワークのデフォルトに依存せず、メタデータをコードで完全掌握すること。それこそが、レガシーシステムを極限まで延命・最適化するプロフェッショナルのアプローチである。
