#10 Databaseオブジェクト変数の通用範囲とオープンするタイミング

結論
データベースを開くにはそれなりに時間が掛かるが、ローカルで使う限りは無視してよい程度である。

クライアントサーバーでは、「Accessの起動時のフォームでデータベースへのログインを行い、以降終了するまでそれを維持しておくとよい」としばしば見聞きします。そこで、データベースにアクセスするたびにデータベースを開いてDatabaseオブジェクト変数を設定する場合と最初に一度だけ設定する場合とで実行時間を比較してみたいと思います。実際には、1回データベースを開くためにどれぐらいの時間がかかるかを調べることになります。本来はクライアントサーバーの環境で行うべき実験ですが、残念ながらその環境がないため、ローカルでJETデータベースエンジンに対してだけ行うものとします。

まず、前者の場合では、プロシージャ内に"Private"でその変数を宣言し、毎回毎回データベースを開くことにします。一方、後者の場合には、標準プロシージャの"Declarations"セクションに"Public"変数を宣言し、データベースへのアクセスが行われたとき、まだその変数が設定されていなければデータベースを開き、すでに設定されていればそのまま何もしないようにします。これは「Databaseオブジェクト変数 Is Nothing」という構文で調べます。また、これらの比較は、カレントデータベースに対するものと外部のデータベース(MDB)に対するものについても行ってみます。

  Dim dbs As Database
  Dim iintLoop As Integer
  
  ts_watch "測定開始", True
  
'毎回データベースを開く
  'カレントデータベースの場合
  For iintLoop = 1 To 100
    Set dbs = CurrentDb
    dbs.Close
  Next iintLoop
  ts_watch "カレントデータベース+Private"

  '外部のデータベースの場合
  For iintLoop = 1 To 100
    Set dbs = DBEngine.Workspaces(0).OpenDatabase("c:\tmp\test2.mdb")
    dbs.Close
  Next iintLoop
  ts_watch "外部データベース+Private"


'最初に一度だけデータベースを開く
  'カレントデータベースの場合
  For iintLoop = 1 To 100
    If (pdbs Is Nothing) Then
      Set pdbs = CurrentDb
    End If
  Next iintLoop
  pdbs.Close:  Set pdbs = Nothing
  ts_watch "カレントデータベース+Public"

  '外部のデータベースの場合
  For iintLoop = 1 To 100
    If (pdbs Is Nothing) Then
      Set pdbs = DBEngine.Workspaces(0).OpenDatabase("c:\tmp\test2.mdb")
    End If
  Next iintLoop
  pdbs.Close: Set pdbs = Nothing
  ts_watch "外部データベース+Public"




そして、テスト結果はつぎのようなものになりました。なお時間の単位は"秒"です。

カレントデータベース 外部データベース
毎回データベースを開く場合(A) 1.28 3.37
最初に一度だけデータベースを開く場合(B) 0.05 0.05
差異(A−B) 1.23 3.32
一回当りのオープン時間の差異(A−B)÷100 0.01 0.03

結果を見るまでもなく、最初に一度だけデータベースを開く方が速いのは当然です。また、一回当りのオープン時間の差異を見る限り、実際のアプリケーションを動作させて感じられるような値ではありません。ただ、実際にそのアプリケーションを動作させる環境でこの値がどう変るかは確認したいところです。一人がローカルで使うデータベースであればこんな時間は完全に無視できるでしょう。一方、サーバーにデータベースがあり、ネットワークで共有している場合には、ネットワークの混み具合やデータベースの利用者数、あるいはデータベースを開く頻度によって無視できない時間と考えられるかもしれません。さらにODBCを使ってサーバーベースのデーターベースにアクセスする場合には、ODBCのスループットやサーバー側のユーザー認証などによって上記の差異はもっと大きくなる可能性もあります。しかしながら、ローカルでかつスタンドアロン環境でしかテストできない場合の結論としては、「データベースを開くにはそれなりに時間が掛かるが、ローカルで使う限りは無視してよい程度である。」ということになると思います。

ところで、今回使ったコードに関してですが、起動時のスタートアップフォームでだけデーターベースを開くコードを記述して、後は一切なしとしてしまうと、プロシージャ単位でデバッグする際に面倒なことになってしまいますが、上記のように「Databaseオブジェクト変数 Is Nothing」で調べるようにすれば、どちらの方法を使っても通用しますので、常にこのようにコーディングしておくというのはけっこう使えるのではないでしょうか?。

また、今回はDatabaseオブジェクトを対象にテストしてみましたが、クロス集計クエリーやサブクエリーを使ったクエリーなどの複雑なクエリーを使って"Recordsetオブジェクト"を開く場合には、相当な時間を要することがあります。そのような場合にも同様に「Recordsetオブジェクト変数 Is Nothing」で調べるという方法を使えばきっと効果があると思います。ちなみにこの手法は、Webによるデータベースのレコード表示で使われることがよくあるようです。何十件も一度に表示しようとするとレスポンスが落ちるので、[次の10件]や[前の10件]というボタンを用意して、10件ずつデータを表示させるという方法です。これは "ページング処理" などと呼ばれているようですが、10件表示させるたびにRecordsetオブジェクトを開くのではなく、最初に一度開いてあとは開き放しにしておくことによってレコードの抽出と表示を高速化しようというものです。やはりWebのようにネットワークを使う環境ではこのような工夫が必要なのかもしれません。

| Index | Prev | Next |

 

Copyright © T'sWare All rights reserved