#04 OpenRecordset メソッドのレコードセットタイプを比べる

結論
OpenRecordset メソッドでのレコードセットタイプの選択はAccessに任せよう!
ただし前方向のみのレコード移動しかないクエリーに対する処理では ForwardOnly を使う価値あり。

Access Labo の#01から#03では OpenRecordset メソッドのパラメータをいくつか比較してみましたが、 OpenRecordset メソッドにはもう一つ重要なパラメータがあります。レコードセットの"タイプ"です。重要でありながらこれがこれが実験の後回しになってしまったのには訳があります。レコードセットのタイプは、OpenRecordset メソッドのソースがテーブルである場合には自動的に "Table" タイプに、またクエリーの場合には "Dynaset" タイプになります。つまり既定値として最適なタイプを自動的に選択してくれるわけです。そのため、特にその違いを気にしていなかったのです。しかし、その既定値はいかなる場合にも最適なのか、またこれ以外のタイプ、つまり "ShapShot" や "ForwardOnly" では処理時間にどのような違いがあるのか、やはり試してみるべきと考え、ここで取り上げてみました。

テストの内容としては、あるテーブル、およびそのテーブルのすべてのフィールドとレコードを単純に取り出すだけのクエリーに対して、5万件のレコード追加とその全レコードの読み込み、全レコードの更新、さらに全レコードの削除をVBAを使って行うものです。コードは次のようなものです。

  Dim dbs As Database
  Dim rst As Recordset
  Dim strName As String
  Dim ilngLoop As Long
  Const cRecMax As Long = 50000

  Set dbs = CurrentDb
  ts_Watch "テスト開始", True

  Set rst = dbs.OpenRecordset("tblTest", dbOpenTable)
  GoSub AddSub
  ts_Watch "テスト1"

  'レコード移動の時間を測定しないようにレコードセットをオープンし直します。
  Set rst = dbs.OpenRecordset("tblTest", dbOpenTable)
  GoSub SelectSub
  ts_Watch "テスト2"

  Set rst = dbs.OpenRecordset("tblTest", dbOpenTable)
  GoSub EditSub
  ts_Watch "テスト3"

  Set rst = dbs.OpenRecordset("tblTest", dbOpenTable)
  GoSub DeleteSub
  ts_Watch "テスト4"

  '以下同様に dbOpenDynaset、Snapshot、ForwardOnly についてテストします。
  'ただし、SnapshotとForwardOnlyでは追加や更新・削除はできないので、時間測定はしません。


  Set rst = dbs.OpenRecordset("qselTest", dbOpenDynaset)
  '以下同様にテーブルの場合と同じパターンでクエリーに対してテストします。

  Exit Sub

AddSub:
  With rst
    For ilngLoop = 1 To cRecMax
      .AddNew
        !Name = "ABCDE"
      .Update
    Next ilngLoop
    .Close
  End With
  Return

SelectSub:
  With rst
    For ilngLoop = 1 To cRecMax
      strName = !Name
      .MoveNext
    Next ilngLoop
    .Close
  End With
  Return

EditSub:
  With rst
    For ilngLoop = 1 To cRecMax
      .Edit
        !Name = "12345"
      .Update
      .MoveNext
    Next ilngLoop
    .Close
  End With
Return

DeleteSub:
  With rst
    For ilngLoop = 1 To cRecMax
      .Delete
      .MoveNext
    Next ilngLoop
    .Close
  End With
  Return


そして、テスト結果はつぎのようなものになりました。なお、ここでの * マークは組み合わせ不可を表しています。また時間の単位は"秒"です。
ソース タイプ 追加 選択 更新 削除
テーブル Table(既定) 32.0 4.4 36.6 15.7
Dynaset 49.9 7.0 60.2 38.2
ShapShot 7.4
ForwardOnly 4.7
クエリー Table(既定)
Dynaset 50.8 6.9 58.9 37.1
ShapShot 7.4
ForwardOnly 4.7

テスト結果から、Accessが決めてくれる既定のタイプは全般的には最適なものと再確認できたのではないでしょうか?

ちょっと意外だったのは ShapShot タイプがそれほど速くないということです。ShapShot タイプでは、複数のユーザーが同時にアクセスするような環境で、レコードセットを読み込んだ後に他のユーザーがそれらのレコードを更新しても、自分がすでに読み込んだレコードには反映されません。つまり他のユーザーによるレコード更新を監視するための何らかの内部処理が必要ないわけですから、時間的な差が出てもいいと思われるのですが、このメリットはやはり実際にLAN接続されているようなマルチユーザー環境でないと無いのでしょうか?(ちなみにこのテストは完全にスタンドアロンで行っています)

もう一つ結果から分かる特徴的なことは、クエリーに対して ForwardOnly を使用すると時間的メリットが出てくるという点です。もちろん、それぞれのタイプによってレコードに対する操作に制限事項がありますので、それについてはその制限を優先して考える必要があります。例えばブックマークなどを使って前後にレコード移動するような処理ではこの ForwardOnly は使えないわけですから、あくまでも「前方向のみのレコード移動ではメリットがある。」ということになります。

| Index | Prev | Next |

 

Copyright © T'sWare All rights reserved