こんにちは!現場でバリバリとAccessやVBAを使ったシステム開発をしていると、避けて通れないのが「データベースの肥大化問題」ですよね。
「機能はそんなに追加していないのに、なぜかMDBやACCDBのファイルサイズがパンパンに膨れ上がっている……」
そんな経験はありませんか?
もしかしたらその原因、テーブルの「Unicode圧縮(Unicode Compression)」プロパティがデフォルトのまま放置されていることにあるかもしれません。
今回は、初学者から一歩抜け出して「現場で使えるエンジニア」を目指すあなたへ、フィールドのUnicode圧縮をVBAで一発制御し、DBの容量をスマートに最適化する極意を伝授します。ここをクリアすれば、Accessの裏側の仕組みまで見通せるエンジニアにグッと近づけますよ!
—
なぜAccessはファイルがすぐ重くなるのか?
Access(特にACCDB形式)では、テキスト型(Short Text)フィールドのデータを内部的にUTF-16(2バイト文字コード)で保持しています。
ここで思い出してほしいのが、日本の私たちが普段使う日本語(全角文字)や英数字の存在です。
- 英数字や記号:本来なら1バイトで表現できるものも、UTF-16では無理やり2バイトを使って保存されます。
- Unicode圧縮:これを防ぐために用意されているのが「Unicode圧縮」機能です。ASCII文字(1バイトで足りる文字)が主体のデータにおいて、上位の「00」のバイトを削って保存し、ファイルサイズを劇的に小さくしてくれます。
🚨 落とし穴:新しく作ったフィールドは「圧縮されない」?
実は、Accessのテーブルデザイン画面で新しく「短いテキスト」フィールドを追加した際、Accessのバージョンや設定によっては、このUnicode圧縮が「いいえ(False)」のままになっていることがあります。
数百万件のレコードを扱う基幹系システムでこれをやらかすと、数GBもの無駄なスペースをドブに捨てることになり、パフォーマンスもガタ落ちします。手動で一つひとつのテーブル、一つひとつのフィールドを開いて「はい」に変えていく……? そんな不毛な作業は、私たちVBAエンジニアの仕事ではありません。コードの力で一網打尽にしましょう!
—
現場で即効!Unicode圧縮を一括切替するVBAコード
それでは、データベース内にあるすべての対象テーブル・フィールドを走査し、強制的にUnicode圧縮を「有効(True)」にするプロシージャを公開します。
標準モジュールに貼り付けて、そのまま実行できるように設計しました。
Option Explicit
”’
”’ Unicode圧縮プロパティを一括で「True(はい)」に設定するプロシージャ
”’
Public Sub OptimizeUnicodeCompression()
Dim db As DAO.Database
Dim tdf As DAO.TableDef
Dim fld As DAO.Field
Dim updatedFieldsCount As Long
‘ 初期化
Set db = CurrentDb
updatedFieldsCount = 0
On Error GoTo ErrorHandler
‘ データベース内の全テーブルをループ(システムテーブルは除外)
For Each tdf In db.TableDefs
‘ 先頭が “MSys” または “~” で始まるシステムテーブル・一時テーブルはスキップ
If (tdf.Attributes & dbSystemObject) = 0 And Left$(tdf.Name, 1) <> “~” Then
‘ 各テーブルのフィールドをループ
For Each fld In tdf.Fields
‘ ① データ型が「短いテキスト(旧: 텍스트型)」かつ
‘ ② 長さが1以上(ハイパーリンク型などを除外)の場合をターゲットにする
‘ ※ DAO.DataTypeEnum.dbText = 10 (短いテキスト)
If fld.Type = dbText Then
‘ エラーハンドリングの準備(プロパティが存在しない例外対策)
On Error Resume Next
‘ UnicodeCompressionプロパティを変更
‘ ※ まだプロパティが存在しないフィールドに直接代入するとエラーになるため、一旦設定を試みる
fld.UnicodeCompression = True
If Err.Number = 0 Then
updatedFieldsCount = updatedFieldsCount + 1
Debug.Print “更新成功: [” & tdf.Name & “].[” & fld.Name & “]”
End If
On Error GoTo ErrorHandler ‘ エラー監視を元に戻す
End If
Next fld
End If
Next tdf
‘ 完了メッセージ
MsgBox “最適化が完了しました!” & vbCrLf & _
“Unicode圧縮を適用したフィールド数: ” & updatedFieldsCount & “件”, _
vbInformation, “DBサイズ最適化”
CleanUp:
Set fld = Nothing
Set tdf = Nothing
Set db = Nothing
Exit Sub
ErrorHandler:
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, _
vbCritical, “エラー”
Resume CleanUp
End Sub
—
コードの重要なポイントを徹底解説
初心者から一歩進んだエンジニアになるために、このコードのキモとなる部分を紐解いていきましょう。
1. DAOライブラリによるテーブル定義(TableDef)へのアプローチ
Access VBAでテーブル構造をいじる場合、ADOではなくDAO(Data Access Objects)を使うのが鉄則です。`CurrentDb.TableDefs`を使うことで、Accessのテーブルの設計図そのものをプログラムから自由自在に操作できます。
2. システムテーブルの華麗なるスルー
`If (tdf.Attributes & dbSystemObject) = 0` という条件式に注目してください。
Accessには、フォームやクエリの情報を裏で保持する `MSysAccessObjects` などの「システムテーブル」が存在します。これらを誤って書き換えようとすると、「そんなことできません!」とAccessに怒られてエラーになります。
現場のコードでは、こうした「触ってはいけない領域」をスマートに避けるガード処理がプロの証となります。
3. 「プロパティがないかも?」を乗り切る `On Error Resume Next`
Accessのフィールドオブジェクトは、データ型やその他の条件によって、持っているプロパティが微妙に異なります。
「UnicodeCompressionプロパティが存在しないフィールド」に対して無造作に値を代入しようとすると、VBAは容赦なく実行時エラー(エラー438: オブジェクトは、このプロパティまたはメソッドをサポートしていません)で停止します。
そのため、あえて一時的に `On Error Resume Next` を使ってエラーをいなし、「設定できたものだけカウントする」という堅牢(ロバスト)な実装にしています。
—
⚠️ 開発現場で絶対に知っておくべき「注意点」
最後に、このUnicode圧縮を扱う上で、プロとして知っておくべき「トレードオフ」についてお話します。
- CPU負荷とのトレードオフ
Unicode圧縮は「保存するときに圧縮し、読み込むときに解凍する」という処理を行います。そのため、ディスク容量(ファイルサイズ)は劇的に小さくなりますが、データの読み書きを行う際のCPUの負荷がごくわずかに増えます。
とはいえ、昨今のPC性能であれば体感できるほどの差はありません。何GBもある巨大なデータを扱うWeb連携システムやローカルDBにおいては、ファイルサイズ縮小のメリットの方が圧倒的に大きいです。
- 「長文テキスト(メモ型)」には効かない
Accessの「長いテキスト(Long Text / 旧メモ型)」フィールドは、そもそも内部構造が異なり、Unicode圧縮プロパティを持っていません(常に圧縮に近い特殊なフォーマットで保持されます)。今回のコードが対象とするのはあくまで「短いテキスト(dbText)」です。
—
おわりに
いかがでしたか?
今回は、テーブル定義の裏側にある「Unicode圧縮」にスポットを当て、VBAでデータベースをスマートに最適化する手法を解説しました。
「ただ動くマクロを書く」段階から、「リソースやパフォーマンスを意識したコードを書く」段階へシフトできると、あなたの書くVBAの価値は跳ね上がります。ぜひ実際の開発環境で試してみてくださいね。
ここをクリアしたあなたなら、もうAccess VBAの基本はバッチリです!
次のステップでも、現場で即役立つ知見を一緒に学んでいきましょう。快適なAccessライフを!
