こんにちは、なかぜんです。
Accessで業務アプリを構築していると、だんだんとクエリが複雑になり、処理速度が気になってくることってありますよね。
「最初はサクサク動いていたのに、データが増えてくると重くなる…」そんな悩みに共感する方も多いのではないでしょうか。
今回は、そんな複雑なクエリを高速化するための最適化テクニックを、Access歴30年の私「なかぜん」が、実践的に解説していきます。
クエリ最適化の基本原則
1. インデックスの確認と活用
まずはデータベース設計の基本ともいえるインデックス。特に、結合やWHERE句で使用されるフィールドにインデックスが設定されていないと、クエリの処理速度は一気に低下します。
CREATE INDEX idx_社員ID ON T_勤怠(社員ID);
Accessのテーブルデザインビューからも、対象フィールドの「インデックス」プロパティを「はい(重複可)」に設定することで対応可能です。
2. 不要なフィールドの読み込みを避ける
SELECT * は便利ですが、すべてのフィールドを読み込むと無駄な処理が発生します。必要なフィールドだけを明示的に指定しましょう。
SELECT 社員ID, 勤怠日, 勤務時間 FROM T_勤怠 WHERE 勤怠日 BETWEEN #2025/01/01# AND #2025/01/31#;
複雑なクエリ構造の見直し
3. サブクエリを分割してテーブル化
AccessはSQL Serverのような最適化エンジンが弱いため、ネストの深いサブクエリや、複数段のJOINは極端に遅くなることがあります。
例えば以下のようなクエリ:
SELECT * FROM
(SELECT 顧客ID, SUM(金額) AS 合計金額 FROM T_売上 GROUP BY 顧客ID) AS 売上合計
INNER JOIN T_顧客 ON 売上合計.顧客ID = T_顧客.顧客ID;
このような場合は、サブクエリを一旦「作業用クエリ」として保存し、別のクエリでJOINする方法が有効です。
4. IIf関数の多用に注意
IIf関数は便利ですが、複雑な条件分岐が大量にあると、クエリのパフォーマンスに影響します。代替手段としては、クエリの事前フィルタリングやVBA側での処理分岐を検討しましょう。
実践例:重い集計クエリの最適化
例:受注データから月次売上を集計するクエリ
SELECT Format(受注日, "yyyy/mm") AS 月度, SUM(金額) AS 合計売上
FROM T_受注
WHERE 受注日 BETWEEN #2024/01/01# AND #2024/12/31#
GROUP BY Format(受注日, "yyyy/mm")
ORDER BY 月度;
改善ポイント:
・日付フィールドにインデックスを設定する
・Format関数による抽出は遅くなるため、あらかじめ「年月」列をテーブルに追加する
改良後の構造
SELECT 月度, SUM(金額) AS 合計売上
FROM Q_年月付き受注データ
GROUP BY 月度;
※ Q_年月付き受注データ は、年月列を持つ作業用クエリ
パフォーマンスに悪影響を与えるポイント
- リンクテーブルでの複雑なJOIN(ネットワーク越しの処理が重くなる)
- 非インデックス項目の結合
- 計算フィールドをJOINやGROUP BYに使用
- VBA関数の直接呼び出し(Nz関数含む)
応用:フォームとの連携で実行時フィルターを活用
パラメータ付きクエリを使うと、フォームから条件を渡して柔軟にクエリを高速化できます。
SELECT * FROM T_売上
WHERE 顧客ID = Forms!F_検索画面!cmb顧客;
これにより、クエリ自体の行数が抑えられ、実行パフォーマンスも向上します。
まとめ:今日からできるクエリ高速化の第一歩
今回は、Accessでよく発生する「クエリが重くなる問題」に対して、実務でも使える具体的な最適化テクニックを紹介しました。
- インデックスの活用
- 不要な列の除外
- サブクエリやFormat関数の見直し
- フォームから条件を受け渡すパラメータ化
どれかひとつでも取り入れるだけで、体感的に処理速度が変わることも多いです。
次のステップ
Accessのパフォーマンスチューニングは奥が深い世界。今後は「インデックスの実行計画の見える化」や「VBAからクエリの動的生成」など、さらに一歩踏み込んだ内容にも挑戦していきましょう。
「なかぜん」でした。この記事があなたの開発の一助になればうれしいです!
