AccScan
技術

Accessのインデックス設計|効く場面・張りすぎの弊害

Accessのインデックスは検索・ソート・結合を速くするが、値の種類が少ない列や更新頻度の高いテーブルでは逆効果になります。1テーブル32個の上限・複合インデックス最大10フィールド・AutoIndexの落とし穴など、公式仕様をもとに設計の考え方を解説します。

まずは、自社のAccessが「解析できるか」を無料で確認できます。

約2分・ファイル送信不要・発注義務なし

結論:インデックスは「張る場所」より「張らない判断」が難しい

Accessのインデックスは、検索・並べ替え・テーブル結合を速くするための仕組みです。主キーには自動で付き、AutoIndex設定に合致するフィールド名や参照整合性を設定した外部キーにも自動で作成されることがあります。それ以外のフィールドは設計者が追加します。問題は、むやみに増やすとレコードの追加・削除やインデックス対象フィールドの値変更のたびにインデックスも書き換えが走るため、逆に遅くなる点です。値の種類が少ない列(ステータス区分など)に単独でインデックスを張っても効果が出にくく、更新コストだけが増えることがあります。

この記事では、インデックスの仕組みと設計の基本を整理します。クエリのチューニング全般(DLookup置き換え・多段クエリの整理など)はAccessクエリ高速化の技術に譲り、ここはインデックス設計に絞ります。

インデックスが何をしているか

インデックスは、フィールド値を基にレコードの格納位置を参照できるようにした内部の索引構造です。インデックスなしで「受注日 = 2024/03/15」を絞り込む場合、テーブルを先頭から全件なめます(テーブルスキャン)。インデックスがあれば、索引をたどって対象レコードの格納場所を特定し、全件走査を避けて取得できます(Create and use an index to improve performance | Microsoft Support)。

Accessのエンジン(JET/ACEの詳細はこちら)に関しては、Jet 4.0時代の公式資料(Access 2002 Desktop Developer's Handbook)にRushmoreテクノロジの説明があります。同資料によると、Rushmoreは複数インデックスのビットマップを組み合わせ、AND条件では積集合・OR条件では和集合で候補を絞る仕組みです(Access 2002 Desktop Developer's Handbook | Microsoft Learn)。現行ACEの内部実装は公開されていませんが、ACEはJETを基盤としており、同資料はJET/ACEの動作を理解する際の参考資料として一般に参照されています。

ただし、インデックスが使われるかどうかはオプティマイザが統計とコストを比較して決めます。選択性の低い列(同じ値が大量にある列)に単独でインデックスを張っても、Microsoft公式ドキュメントは「速度が大きく改善しない可能性がある」としており、場合によっては走査の方が速いとオプティマイザが判断するケースもあります。値の種類が少ない列を単独でインデックス化する際は、代表的なクエリで実測して判断してください。

インデックスが効く場面と効かない場面

場面インデックスの効果補足
WHERE句で特定の値を絞り込む(等値検索・範囲検索)大きいフィールドに選択性がある(値の種類が多い)こと前提
ORDER BY でソートする条件次第ORDER BYと適合するインデックスがある場合、追加ソート処理を省略できる場合がある
テーブル結合(JOIN)の結合列大きい結合列に適切なインデックスがないと、全件走査を伴う高コストな計画になる場合がある
WHERE句でフィールドに関数をかける(例: Format(受注日, "yyyy")なし関数の結果はインデックスと一致しないためスキャンになる
値の種類が少ない列への単独インデックス(ステータス区分・性別など)限定的データ分布と検索条件に依存する。複合インデックスの一部としては有効な場合もある
データ量が少ないテーブル限定的全件走査のコストが低い場合は効果が限定的。行数だけでなくレコード幅などによっても変わるため実測で判断する

張りすぎの弊害:更新コストと容量

インデックスは「読む速さ」と「書く遅さ」のトレードオフです。レコードを追加・削除したり、インデックス対象フィールドの値を変更したりするたびに、対応するインデックスの書き換えが走ります(Create and use an index to improve performance | Microsoft Support)。インポートや一括更新など大量書き込みが伴う処理では、インデックスが多いほどオーバーヘッドが積み重なります。

また、インデックスもデータベース容量を消費します。不要なインデックスが増えると2GBの壁に近づくのが速くなる場合があります。不要なインデックスを整理することは、容量管理の面でも有効です。

当社の経験では、インポート処理が年々遅くなっていたケースで、いつの間にか同じフィールドにAutoIndex由来のインデックスと手動追加のインデックスが重複して存在していたことがありました。テーブルのデザインビューでインデックス一覧を定期的に確認する習慣を持っておくと安心です(当社実務経験に基づく参考例です)。

主キー・一意インデックス・複合インデックスの使い分け

主キーは自動でインデックスが作られ、NULL不可・重複不可の制約が付きます。旧Jet資料によると、一意インデックスは非一意インデックスよりも統計情報をより正確に扱えるとされており、主キー・外部キーによる結合を基本として設計します。実際の結合順序はオプティマイザが判断します(Access 2002 Desktop Developer's Handbook | Microsoft Learn)。

主キー以外でも値が一意なフィールド(例: 社員番号・メールアドレス)には「重複なし(No Duplicates)」の一意インデックスを使います。旧Jet資料では、一意インデックスは非一意インデックスより正確な統計情報を利用できるとされています。現行ACEでの詳細は公開されていませんが、一意性の制約としての意味でも有用です(前述のMicrosoft Learnドキュメント参照)。

複合インデックス(複数フィールドの組み合わせ)は、「同時に絞り込むことが多いフィールドの組み合わせ」に対して有効です。たとえば「顧客IDと受注日」で絞り込むクエリが頻繁にあるなら、その2フィールドの複合インデックスが単体インデックスより速くなる場合があります。フィールドの順序も重要で、等値条件で使うフィールドを先頭に置き、次いで範囲条件・ソートに使うフィールドを続けるのが基本の考え方です。複合インデックスに含められるのは最大10フィールドまでですが、当社の経験では2〜3フィールドで組むことがほとんどです(Access の仕様 | Microsoft Support)。

なお、1テーブルに作れるインデックスの上限は32個です(参照整合性で自動作成されるものを含む)(前述のAccess仕様ページ参照)。複数の外部キーを持つテーブルで参照整合性を多数設定していると、思いがけず消費されていることがあります。

インデックス設定の手順

単一フィールドのインデックスはテーブルのデザインビューから設定できます。対象フィールドを選んで、フィールドプロパティの「インデックス」欄を以下のいずれかに変更します。

設定値意味使い所
いいえ(なし)インデックスなし絞り込みや結合に使わないフィールド
はい(重複あり)通常のインデックス重複値があるフィールドへの検索・ソート・結合
はい(重複なし)一意インデックス値が一意なフィールド(社員番号等)

複合インデックスはデザインビューのリボン「テーブルデザイン」タブにある「インデックス」ボタンから設定します。最初の行にだけインデックス名を入力し、フィールド名と並べ替え順序(昇順・降順)を指定します。続く行はインデックス名を空欄にして次のフィールドを指定すると複合インデックスになります(Create and use an index to improve performance | Microsoft Support)。

AutoIndexについても確認しておきます。AccessはフィールドID・Key・Code・Numなどで名前が始まるか終わるフィールドを作成時に自動でインデックス付きにします(設定は「ファイル」→「オプション」→「オブジェクトデザイナー」で変更可能)。意図せずインデックスを生成しているケースがあるため、テーブルのインデックス一覧で確認しておくと無駄がありません。

旧Jet資料には、インデックスを追加・変更した後にクエリを保存し直すと再コンパイルが走り実行計画が更新されるという記述があります(前述のMicrosoft Learnドキュメント参照)。現行ACEで同じ動作が保証されるかは公開情報では確認できていませんが、インデックスを追加しても速度改善が見られない場合は試してみる価値があります。

インデックス設計と並行して、テーブル設計の正規化も見直すと効果的です。Accessのテーブル設計と正規化で基本設計の考え方を解説しています。

自社のAccessについて「どこにボトルネックがあるか分からない」という場合は、無料の解析可否チェックでファイルを送らずに仮判定できます。

よくある質問

Q. 主キーがあればインデックスは不要ですか?

主キーのインデックスで対応できるのは、主キー列を使った検索・結合・ソートのみです。外部キー列(別テーブルの主キーを参照するフィールド)にも、結合性能のため通常はインデックスが必要か確認します。参照整合性を設定したリレーションシップではAccessが外部キー列にも自動でインデックスを作成しますが、結合線を引いただけ(参照整合性なし)の場合は作成されません。外部キー列はとくに見落としやすいポイントです。

Q. インデックスを増やしたら逆に遅くなりました。

原因として多いのが2つあります。1つは選択性の低い列(値の種類が少ない列)への単独インデックスで、オプティマイザがインデックスを使わず走査を選びつつ、更新時のインデックス書き換えだけオーバーヘッドが増えているケースです。もう1つはAutoIndexで既に付いていたインデックスに手動で重複を追加したケースです。インデックス一覧を開いて、同じフィールドへの重複や使われていないインデックスがないか整理してください。

Q. 1テーブルのインデックスは何個まで作れますか?

上限は32個です。参照整合性の設定で自動作成されるインデックスもこの数に含まれます(Access の仕様 | Microsoft Support)。複数の外部キーを持つテーブルで参照整合性を多数設定していると、思いがけず消費されていることがあります。

Q. インデックス設計よりも先にやるべきことはありますか?

「データベースツール」タブの「パフォーマンスアナライザー」を先に走らせることをお勧めします。インデックス不足の指摘があれば対象フィールドが絞り込まれるため、手当たり次第に張るより効率的です。アナライザーはテーブル・クエリ・フォームなど全オブジェクトを対象に走らせられます。クエリ全般のチューニングについてはAccessクエリ高速化の技術も参照してください。

触れないAccessが「診断できるか」だけ、確かめませんか。

顧客データは送信不要。発注の義務もありません。

約2分・ファイル送信不要・発注義務なし/説明はオンライン・売り込みはしません