通过“缓存”表或其他策略访问增加DLookup的速度?

时间:2014-02-21 19:16:24

标签: sql vba ms-access access-vba ms-access-2010

背景

我有一个带multiple DLookups的Access拆分表单。表单上总共有大约10个DLookup,并且在Splitform视图中一次显示大约25-50条记录。

Access前端链接到SQL表。

当在数据表视图中显示DLookup值时,查看信息变得非常慢,因为频繁重新计算(每次数据集中的任何内容更改时,Access都会重新计算整个Splitform数据表的所有DLookup)。当通过VPN连接时,这非常明显且无法接受。

研究

我决定调查并撰写以下内容以确定事情为何如此缓慢。我还想检查DLookup是否由于某种原因而比SQL查询慢。

sub testLotsofDlookups()

    Dim count As Integer
    Dim startTime As Date
    Dim endTime As Date
    Dim numbTries As Integer
    Dim t As String

    numbTries = 100
    startTime = Now
    count = 0

    Dim dbs As DAO.database
    Dim rsSQL As DAO.Recordset
    Dim strSQL As String

    Set dbs = CurrentDb

    'Open a snapshot-type Recordset based on an SQL statement
    strSQL = "Select FullName from ToolDesigners Where ToolDesignersID=4;"

    startTime = Now
    For count = 1 To numbTries
        Set rsSQL = dbs.OpenRecordset(strSQL, dbOpenSnapshot)
        t = rsSQL.Fields(0)
    Next count
    Dim mDiff As Double
    mDiff = DateDiff("s", startTime, Now)
    Debug.Print "SQL Total time:" & vbTab & DateDiff("s", startTime, Now)
    Debug.Print "SQL Average time:" & vbTab & mDiff / numbTries

    '
    '
    '
    '
    '



    startTime = Now

    For count = 1 To numbTries
        t = DLookup("FullName", "ToolDesigners", "ToolDesignersID=4")
    Next count


    mDiff = DateDiff("s", startTime, Now)
    Debug.Print "DLookupUp Total time:" & vbTab & DateDiff("s", startTime, Now)
    Debug.Print "DLookupUp Average time:" & vbTab & mDiff / numbTries

end sub

(我知道这只能精确到单秒)

有趣的是,我发现平均每个DLookup和SQL查询耗时近0.5秒。在公司内部网上工作时,我的平均时间仍然超过0.10秒。两者的速度都非常可比。

这会导致非常慢的表单刷新以及非常慢的数据表刷新。

然后我对我机器上托管的SQLExpress数据库进行了测试 - 平均下降到0.0005秒。

问题

似乎DLookups在这个应用程序中很慢。我希望找到另一种更快捷的方法。

喜欢能够做的是以某种方式导致DLookup针对本地表运行Access可能会保留而不是服务器上的SQL表。看来我每次打开表单或数据库(不是粉丝)都可以创建临时表 - 有更好的方法吗?

如果我指的是另一个Access数据库,我可以使用“opendatabase”然后将其保存在内存中。然后,这会提高对该数据库的查询速度。我发现100%的例子都是指Access数据库,而不是SQL。

或者我可以使用DLookup以外的东西,这是我在测试SQL命令时的想法,但我不确定该怎么做,因为SQL速度相当。

1 个答案:

答案 0 :(得分:7)

如果它只是单个值,那么我倾向于使用简单的内存缓存 -

Private mToolDesignerFullNameCache As New Scripting.Dictionary

Function GetToolDesignerFullName(Criteria As String)
  If mToolDesignerFullNameCache.Exists(Criteria) Then
    GetToolDesignerFullName = mToolDesignerFullNameCache(Criteria)
  Else
    Dim Name
    Name = DLookup("FullName", "ToolDesigners", Criteria)
    mToolDesignerFullNameCache.Add(Criteria, Name)
    GetToolDesignerFullName = Name
  End If
End Function

Sub ResetToolDesignerFullNameCache()
  mToolDesignerFullNameCache.RemoveAll
End Sub

需要添加“Microsoft Scripting Runtime”作为VBA引用进行编译。在过去,我发现这种事情很有用,即使在使用Access后端时,Access UI将轮询数据的频率。