#47 | クエリパフォーマンスの定石を試す(1) | ||||||||||
クエリ(SQL文)の実行時のパフォーマンスを上げるために一般的に言われていること、すなわち”定石”がAccess(JETデータベースエンジン)でも同様に通じるのかを試す第1弾です。今回は、『SELECT * は使わない』という定石を確認してみました。 SELECT文を書く場合、基本的な構文としては「SELECT フィールド名, フィールド名, ・・・・・」という書き方を使います。しかし、テーブルに保存されているすべてのフィールドを取り出したい場合には、省略形として「SELECT * 」という記述が使えます。 これは、クエリオブジェクトとして作る場合には、デザインビューにおいてフィールドリストから「*」をグリッドに配置すること、もしくはグリッドにフィールドを何も配置しないでクエリプロパティの「全フィールド表示」を”はい”に設定することによって内部生成されるSQL文になります。 この場合、一般的には『「SELECT *」ではすべてのフィールドが取り出されるため、もしそのあとにすべてのフィールドデータを取り扱わない場合には不必要なオーバーヘッドが発生してしまうため、必要なフィールドのみを列挙すべき』と言われているものです。 そこで今回は、「SELECT *」と「SELECT フィールド名, フィールド名, ・・・・・」でどの程度実行時間が違うか、それらを実際に比較することによって定石を検証してみたいと思います。 今回の実験では、総レコード数10万件のテーブルを用意しました。また、”読み込むフィールド数によってパフォーマンスへの影響があるだろう”という前提ですので、少ないフィールド数では「*」と「フィールド名, フィールド名, ・・・・・」の違いが出づらいはずです。そこであえて多めのフィールドを用意しました。長さ20のテキスト型のフィールドを50ケ用意してあります。 そして、実行してみるテストパターンは次の2つです。いずれも場合、テーブルを開いたあと、全レコードをトレースし、6つのフィールドのデータをダミー変数に代入するだけという処理です。処理対象フィールドは、50ケのフィールド位置の影響もあるかもしれませんので、均等にアクセスされるよう等間隔で取るようにしています。
テスト用のコードは次のようなものです。OpenRecordsetメソッドの引数に与えるSQL文を除いては2つのテストパターンに違いはありません。 Sub QueryPerformance_1() Dim dbs As Database Dim rst As Recordset Dim strSQL As String Dim iintLoop As Integer Dim strDummy As String ts_Watch "処理開始", True Set dbs = CurrentDb For iintLoop = 1 To 10 'テストパターン1 strSQL = "SELECT * FROM tblテスト" Set rst = dbs.OpenRecordset(strSQL) With rst Do Until .EOF strDummy = !フィールド01 strDummy = !フィールド11 strDummy = !フィールド21 strDummy = !フィールド31 strDummy = !フィールド41 strDummy = !フィールド50 .MoveNext Loop .Close End With ts_Watch "SELECT *" 'テストパターン2 strSQL = "SELECT フィールド01, フィールド11, フィールド21, " & _ "フィールド31, フィールド41, フィールド50 " & _ "FROM tblテスト" Set rst = dbs.OpenRecordset(strSQL) With rst Do Until .EOF strDummy = !フィールド01 strDummy = !フィールド11 strDummy = !フィールド21 strDummy = !フィールド31 strDummy = !フィールド41 strDummy = !フィールド50 .MoveNext Loop .Close End With ts_Watch "SELECT フィールド名" Next iintLoop End Sub その結果は次のようになりました。
ご覧のように、結果は明らかに”定石”通りになっています。フィールド50ケを読み込むか、あるいは6ケだけを読み込むかの違いがその時間差に出ていると思われます。 これらのことから、「SELECT *」はなるべく使わず必要なフィールドだけをSELECTの次に列挙する方が高速であるということがいえます。 ただし、フィールド数が数ケしかないテーブルの場合にはまたその違いは変わってくるかもしれません。おそらく両者の差は縮まるはずです。また、50ケのフィールドがあろうが100ケのフィールドがあろうが、その後処理でそれら全部のフィールドのデータを処理する場合、クエリオブジェクトは使わずそれをVBAのコード上で組み立てるとなると、後者の書き方ではSQL文が長くなってメンテナンスも大変です。よって、テーブルのフィールド総数と読み込み後の処理で使うフィールド数の差が少ない場合、すなわちテーブル上のフィールドのほとんどを必要とする場合には「SELECT *」という書き方もあながち間違いではないように思います。 |
|||||||||||
|
Copyright © T'sWare All rights reserved |