【入門編】DAOのFindFirstメソッドで「Like演算子」のワイルドカード検索を高速化するインデックス活用術 – Access VBA解析バイブル

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

Access VBAを掌握せよ:FindFirstの「遅延」を消し去るインデックス戦略

こんにちは。現場で泥臭いトラブルをいくつも乗り越えてきた、一人のアーキテクトです。

Access VBAを使っていて、「`FindFirst`で検索をかけたら、レコードが増えるごとにアプリが重くなっていく…」と頭を抱えたことはありませんか?特にリンクテーブルを使っている場合、その「もっさり感」は致命的です。

今日は、DAOの`FindFirst`を魔法のように高速化する「インデックス活用術」を、技術の本質から解説します。これをマスターすれば、あなたのAccessアプリは劇的に軽快になります。

1. なぜ「Like演算子」を使うと検索が遅くなるのか?

まず、敵を知りましょう。`rs.FindFirst “Name Like ‘A*'”` と書いたとき、Accessの裏側で何が起きているかご存知ですか?

もし`Name`フィールドにインデックスが貼られていない場合、Accessは「テーブルの先頭から最後までのレコードを一つずつ開いて、名前がAから始まるかチェックする」という作業(フルテーブルスキャン)を行います。

データが1,000件なら平気ですが、10万件を超えた瞬間にアプリはフリーズしたかのように固まります。これが「重い」の正体です。

2. インデックスを「味方」にするための鉄則

インデックスは、辞書の「索引」と同じです。目的のデータがどこにあるか、あらかじめ地図を作っておく技術です。

鉄則:前方一致(A*)で検索せよ

インデックスが有効なのは、基本的に「前方一致」です。

  • `”Name Like ‘A*'”` → 爆速(インデックスが効く)
  • `”Name Like ‘*A*'”` → 激遅(インデックス無視!全件走査になる)

`*`(ワイルドカード)を先頭に持ってくると、インデックスは無力化します。「何で始まるか」を特定するのが、高速化の第一歩です。

3. 実践:FindFirst高速化コード例

では、実際に現場で使えるコードを見てみましょう。テーブルの特定のフィールドに対して効率的に検索を行うテンプレートです。

Public Sub FindRecordFast()
    Dim db As DAO.Database
    Dim rs As DAO.Recordset
    Dim strCriteria As String
    
    Set db = CurrentDb
    ' ダイナセットタイプで開くのが鉄則
    Set rs = db.OpenRecordset("T_Customer", dbOpenDynaset)
    
    ' 検索条件:前方一致に絞ることでインデックスを有効活用
    ' ※Nameフィールドに必ずインデックスを貼っておくこと!
    strCriteria = "CustomerName Like '株式会社*'"
    
    rs.FindFirst strCriteria
    
    ' 検索結果の判定
    If rs.NoMatch Then
        MsgBox "該当する顧客は見つかりませんでした。", vbExclamation
    Else
        MsgBox "見つかりました: " & rs!CustomerName
    End If
    
    ' 後処理(メモリ解放の作法)
    rs.Close
    Set rs = Nothing
    Set db = Nothing
End Sub

このコードのポイント

1. dbOpenDynasetの活用: リンクテーブルを扱う場合、`Dynaset`として開くことで、Accessエンジンが最適化されたクエリをサーバー側(あるいはリンク先)に投げやすくなります。
2. NoMatchプロパティ: `FindFirst`の直後には必ず`NoMatch`を確認してください。これをサボると、見つからなかった場合にエラーが連鎖します。
3. インデックスの確認: 何よりもまず、テーブルデザインビューで対象フィールドの「インデックス」を「はい(重複なし)」または「はい(重複あり)」に設定してください。ここが全てです。

4. アーキテクトからのアドバイス:それでも遅いときは?

もしインデックスを貼っても遅いなら、それは「ネットワークの帯域」か「クエリの複雑さ」が原因です。

  • リンクテーブルの罠: リンク先がネットワーク上の共有フォルダにある場合、そもそもレコードセットを全件読み込もうとするだけで遅延します。
  • 解決策: `FindFirst`を使う前に、`rs.Filter`でサーバー側で絞り込みをかけるか、最初から検索結果だけを抽出した「パススルー・クエリ」や「SQLによる抽出」を検討してください。

まとめ:ここをクリアすれば、あなたはもう中級者

  • Like演算子は「前方一致(A*)」で使うべし。
  • 検索対象フィールドには必ずインデックスを貼るべし。
  • コードの最後には必ず`rs.Close`と`Nothing`で後始末すべし。

Access VBAは、古い言語だと思われがちです。しかし、DAOやインデックスの仕組みを理解して書かれたコードは、驚くほどモダンで高速に動作します。

「動けばいい」から「速く、正しく動かす」へ。この一歩を踏み出せたあなたなら、どんな業務システムも自在に操れるはずです。ぜひ、現場のコードで試してみてください!

また次回、さらに深い「ADOとDAOの使い分け」の領域でお会いしましょう。

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