通过“缓存”表或其他策略来提高 DLookup 的访问速度?

Posted

技术标签:

【中文标题】通过“缓存”表或其他策略来提高 DLookup 的访问速度?【英文标题】:Access increase speed of DLookup by "caching" tables or other strategy? 【发布时间】:2014-02-21 19:16:24 【问题描述】:

背景

我有一个带有 multiple DLookups 的 Access 拆分表单。表单上总共有大约 10 个 DLookup,Splitform 视图中的任何时候都会显示大约 25-50 条记录。

Access 前端链接到 SQL 表。

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

研究

我决定进行调查并编写以下内容以确定为什么事情如此缓慢。由于某种原因,我还想检查 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 秒。在公司 Intranet 上工作时,我的平均时间仍然超过 0.10 秒。两者在速度上非常相似。

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

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

问题

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

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

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

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

【问题讨论】:

【参考方案1】:

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

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 UI 轮询数据的频率,即使在使用 Access 后端时,我也发现这类事情很有用。

【讨论】:

+1 我也在考虑类似的事情。对于@enderland,我认为这是一个“DLookup 数据的波动性如何?”的问题。对于相对静态的查找,像这样的东西可能会工作得很好。 (p.s. 你最近为 SO 做出了很多非常好的贡献。谢谢!) 啊,这太明显了,我几乎无法处理它。我想说我以前从未使用过这些对象或做过类似的事情,但是,我不能。我打算在星期一试试这个(这实际上让我想在今天晚些时候呆在这里,因为我无法想象它不能很好地工作) - 我的 99.9% 的查找都是静态的,这会让我觉得很荒谬时间! 这是加快许多此类查找的好方法。非常感谢!

以上是关于通过“缓存”表或其他策略来提高 DLookup 的访问速度?的主要内容,如果未能解决你的问题,请参考以下文章

LRU缓存替换策略及C#实现

本地应用缓存算法和缓存策略的介绍

新的浏览器缓存策略变更:舍弃性能确保安全

源码级MyBatis缓存策略(一级和二级缓存)

强缓存与协商缓存

mybatis缓存机制