通过“缓存”表或其他策略来提高 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 的访问速度?的主要内容,如果未能解决你的问题,请参考以下文章