相関サブクエリを検討するときは注意してください。それらは非常に遅くなる可能性があります。また、 2つの相関するサブクエリを含むクエリを作成すると、問題が拡大します。
ソーステーブルに含まれる行数が少ない場合(たとえば数十行)、速度の低下は問題にならない可能性があります。ただし、テーブルに1000行が含まれている場合は、間違いなくそれに気付くでしょう。また、JOINT
フィールドにインデックスが付けられていない場合、パフォーマンスが非常に遅くなる可能性があります。
Accessセッション内からクエリを実行する場合は、相関サブクエリの代わりにドメイン関数(DMin
および)を使用できます。DMax
ドメイン機能はしばしば遅いと批判されます。ただし、この状況では、相関するサブクエリよりも劇的に高速になる可能性があります。
訂正DMin()
:およびDMax()
関数を使用できるようにするために、Accessセッション内からクエリを実行する必要はありません。に基づいてADOレコードセットを開くVBScriptの例を添付しましたqryDomainFunctions
。エラーなしで動作し、正しく報告しますRecordCount: 1000
joints
主キーとして長整数フィールドを使用してテーブルを作成し、joint
1000行を追加しました。次に、次の2つのクエリを作成しました。
qryCorrelatedSubqueries:
SELECT
a.joint,
(SELECT TOP 1 joint
FROM joints b
WHERE b.joint>a.joint
ORDER BY joint) AS Ahead,
(SELECT TOP 1 joint
FROM joints b
WHERE b.joint<a.joint
ORDER BY joint DESC) AS Behind
FROM joints AS a;
qryDomainFunctions:
SELECT
j.joint,
DMin("joint","joints","joint > " & [joint]) AS joint_ahead,
DMax("joint","joints","joint < " & [joint]) AS joint_behind
FROM joints AS j;
QueryDuration
これは、以下の関数を使用して、これら2つのクエリの速度を比較したイミディエイトウィンドウからのトランスクリプトです。この関数は、期間をミリ秒単位で返します。
? QueryDuration("qryDomainFunctions")
0
? QueryDuration("qryCorrelatedSubqueries")
889
joints
これらのクエリは両方とも、フィールドのインデックスの恩恵を受けることに注意してください。インデックスを削除し、データベースを圧縮して、テストを再実行すると、次の結果が得られました。
? QueryDuration("qryDomainFunctions")
16
? QueryDuration("qryCorrelatedSubqueries")
4570
これは私が使用したコードのモジュールです。QueryDuration
パフォーマンス測定の最後の言葉ではありません。ただし、これら2つのクエリの相対速度の大まかなアイデアを提供するのに十分です。
Option Compare Database
Option Explicit
Private Declare Function apiGetTickCount Lib "kernel32" _
Alias "GetTickCount" () As Long
Public Function QueryDuration(ByVal pQueryName As String) As Long
Dim db As DAO.Database
Dim lngStart As Long
Dim lngDone As Long
Dim rs As DAO.Recordset
Set db = CurrentDb()
lngStart = apiGetTickCount() ' milliseconds '
Set rs = db.OpenRecordset(pQueryName, dbOpenSnapshot)
If Not rs.EOF Then
rs.MoveLast
End If
lngDone = apiGetTickCount()
rs.Close
Set rs = Nothing
Set db = Nothing
QueryDuration = lngDone - lngStart
End Function
DomainFunctionsQuery.vbs:
Option Explicit
Dim cn, rs
Set cn = CreateObject("ADODB.Connection")
cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
"Data Source='database1.mdb'"
Set rs = CreateObject("ADODB.Recordset")
rs.CursorLocation = 3 ' adUseClient '
rs.Open "qryDomainFunctions", cn, 3 ' adOpenStatic = 3 '
WScript.Echo "RecordCount: " & rs.RecordCount
rs.Close
Set rs = Nothing
cn.Close
Set cn = Nothing