<インデックスがなぜ必要か?>

インデックスは,普通のテーブルと共に,インデックステーブルとして .mdbファイルの中に保存されています。(詳細は未公表)

アクセスでは,メモリ上のレコードセットの領域を以下のように確保しています。

(メモリの量 - 12MB)/ 4  + 512KB

例えば,メモリの搭載量が,64MB のパソコンの場合,

(64MB - 12MB)/4 + 512KB

= 52*1024/4 + 512         ( 1MB = 1024KB )

= 13824 KB

13.5MBになります。 これ以上のレコードセットは,ハードディスク上の仮メモリ上に呼び出されます。CPUは,メモリ上のデータしかアクセスできないので,ハードディスクの仮メモリ上のデータにアクセスするときは,メモリ上のデータハードディスク上のデータを交換(スワッピング(swapping) といいます。)してから,そのデータにアクセスします。 その交換の作業分だけ実行速度が遅くなります。

Raceテーブルの1レコードの長さは,899byte です。

Raceテーブルのインデックスは,217byteです。

ジェットデータベースでは,テーブル上のレコードを検索するときに,インデックスがあるフィールドについては,インデックステーブルのみを呼び出します。 しかし,インデックスの設定されてないフィールドに対しては,レコードセットすべてを呼び出してしまいます。

Raceテーブルの場合だと,スワッピングが起きないレコード数は,

13824*1024/899 = 15746 レース    (1KB = 1024byte)

13824*1024/217 = 65233 レース (注)    (1KB = 1024byte)

になります。実際に開くときは,RaceUmaテーブルのデータも呼び込まれるので,この時点でメモリ上がいっぱいになってしまうと,開くときに,スワッピングが起き実行速度が遅くなります。 14年5ヵ月分の分のレース数は,60870 なので,インデックスがあるとないのでは,差がでます。

これはよくある説明です。 (本題はここから)

しかし,SQL文に 条件(WHERE句)を設定して外部テーブルのレコードセットを開くときは,そうなのかも知れませんが,ローカルテーブル(開く側の .mdbファイル内のテーブル)やリンクテーブル(開く側の .mdbファイル内でリンク情報を設定した外部テーブル)を開くのに,Accessで DoCmd.OpenForm に条件を設定したときは,あまりこのインデックスの違いがでません。以下の注を参考。

(注)  実際は,インデックステーブルのすべてのデータは呼び出されません。 そのためメモリ上をインデックスデータはあまり占領しません。 このノウハウが,データベースの性能を左右しているようです。 また,DAO等を使って,ふつうのテーブルを開くときも,最初は,先頭レコードしか開きません。その後に必要なレコードを認識していきます。(このことを populate するといいます。)

例えば,検索ページを 東京 1600 芝 4才上or5才上 900万 でレースタイム入線を開くと,14年5ヵ月分のレースから全127レースが検索されますが,(Access2000 Jet 4.0 で行いました。)

各項目のすべてに インデックス あり

13

競馬場名以外の インデックス なし

17

まったくインデックスなし

22

タイム差は,9秒でした。 9秒も違うと見るか9秒しか違わないと見るかは意見の分かれるところですが,少なくとも,結果から見ると,Access参考書や各データベースの専門書に書いてあること,つまり,インデックスが設定されていないとフィールドを読み込んでしまう。 ということは,うそのようです。なぜなら,全フィールドを読み込むと,(レースタイム入線を検索をかけないでメイン画面から開くとわかるのですが,) 43秒もかかってしまうからです。

(これは,Access参考書を書いている人は,SQLServerの専門家である場合がほとんどですので,スタンドアローン(1台のパソコン)の状態で何十万件のデータを扱った経験がないためだと思われます。 個人ベースで何十万件のデータを扱う人なんてJRA-VANユーザーのみだと思います ... ) 

実際には,ジェットデータベースでは,インデックスがなくても全フィールドを読み込むようなことはしていません。 公開されていないのであくまで推測ですが,英文で書かれているものなどを読むと,主キーで各レコードをたどっていき(populateしていき)必要なフィールドのインデックスを一時的に作成して(この時の作業が上記の 9秒差になっているものと思われます。),それで検索して主キーのレコードを絞り込んでからレコードセットを読み込んでいるようです。

インデックスに関しての結論としては,ジェットデータベースでデータを扱う場合,インデックスがないと,一時的なインデックスを作るのに時間が多少かかるので,少なくとも,よく検索する項目については,作ったほうがいい。 という感じでしょうか ...