加载时为什么我的访问数据库这么慢?

问题描述 投票:1回答:2

首先,我读过这篇文章; What is causing my access database to be so slow?

但就像8年前一样,我觉得我可以再问这个问题。

我有一个访问2016数据库,有一个后端SQL服务器,我用于数据库上的所有计算。数据库用于拥有多个作业数据,每个用户都可以在作业之间切换以查看数据。

它在计算方面相当复杂,但数据库本身的大小只有15mb。一直加载每个表单几乎需要10秒钟,从用户的角度来看几乎无法使用。

关于加速数据库的最佳方法有什么建议吗?它位于远程服务器上,每个用户都登录到远程服务器以使用它。所以没有数据库拆分或任何东西。我再次在网上阅读这些文章,如http://www.granite.ab.ca/access/performancefaq.htmhttp://www.granite.ab.ca/access/performanceldblocking.htm

但同样,正如多年前讨论过的那样,我只是想知道是否有更新的方法可以让数据库更快地运行。

问候,迈克尔

sql ms-access access-vba
2个回答
3
投票

re:您“将计算移动到后端SQL Server”

我假设您的意思是您将数据移动到后端服务器。这并不意味着计算在那里发生,或者更快。

事实上,它更有可能增加计算时间,因为计算仍然由运行查询的任何机器完成(我假设你的前端,除非你在后端执行了一些奇特的编码来执行SQL存储过程等,并从那里检索您的数据)。

...所以现在它仍然是像以前一样执行计算的机器 - 但是现在每次运行查询时都必须将数据从服务器拉到本地机器,而不是之前,当数据已经是本地时。


常见的罪魁祸首

没有看到你的数据库,没有人可以做更多的猜测,我的猜测是你有多个设计不良的查询填充正在打开的每个表单。

...可能是同一个查询的各种形式一次又一次地运行?例如,我的经验中的一个常见问题:是否有一个组合框,其中列出了员工姓名或其他数据,这些数据基于各种标准而受到限制?也许每个表单都必须运行类似的查询?可能会对几种形式中的每种形式进行多次查询?

像这样的重复工作量需要简化,如何做到这一点取决于您的情况。通过上面的示例,每次员工列表更改时都可以生成静态表,其中仅包括应包含在组合框中的名称。该表可以存储在本地,从而可以替换每个数据库打开时多次计算的重复查询。

另一个常见错误是在查询中使用耗时的自定义函数,该查询必须针对数千条记录运行该函数。当单个查询调用10,000次时,运行需要四分之一秒的函数可能会成为一个真正的问题。


定时每一步

确定哪个进程导致大部分延迟的有点混乱但有效的方法是通过调用一个记录每个进程运行时间的过程进入并“严重”查看代码。 (我刚刚完成了这项工作,这大大减少了处理“巨大”文件所需的时间。)

下面是我打了一个例子的程序。您想要记录多少或多少取决于您的情况(以及您诊断问题的速度)。

请记住,这是为了临时使用,因为它会增加额外的处理时间(虽然没有你现有的流程那么多,但它的声音!)


示例实现

当您打开数据库时,可能会发生一些事情。也许你有一个运行一个过程的AutoExec宏,它打开表单并运行调用函数等的查询。

这里的目标是弄清楚每个步骤需要多长时间。这是一个糟糕的例子,但希望它是有道理的:

Sub YourOnOpenProcedure()
                                '<-- add our logging sub here
    SomeProcessYouCall_1
                                '<-- add our logging sub here
    SomeProcessYouCall_1
                                '<-- add our logging sub here
    SomeFormYouOpen
                                '<-- add our logging sub here
    SomethingElseYouDo
                                '<-- add our logging sub here (no 'EventName')
End Sub

Function SomeFunctionCalledByYourQuery() As Integer
                                '<-- add our logging sub here
    SomeFunctionCalledByYourQuery = 1 + 2

End Function

程序 - 计时程序

添加此过程和变量或类似于公共模块的东西:

Option Compare Database
Option Explicit   ' <-- Always, especially when troubleshooting!

Public startTime As Single, prevEventName As String

Sub timeIt(eventName As String)
'call this sub with the name of an event/process/sub/form/etc you're about to run
'prints time of previous event, and prepare for the next one if specified
'specify an empty string ("") after the end of the last event to return the last runtime.
    If startTime <> 0 Then   'log the duration of the last event
        'log the previous event
        Debug.Print "-> " & prevEventName & ":",  Round(Timer - startTime, 1) & " seconds"

        'optional: log "event' in a local table  (needs table, see notes)
        'DoCmd.SetWarnings False 'supress record-append confirmation
        'DoCmd.RunSQL "insert into tblLog select '" & prevEventName & "' as eName, " & Timer - startTime & " as eRunTime"
        'DoCmd.SetWarnings True

        startTime = 0
        prevEventName = ""
    End If
    If eventName <> "" Then
        startTime = Timer 'prepare for the next event
        prevEventName = eventName
    End If
End Sub

在表中记录数据是可选的(请参阅下面的表设置),具体取决于您的情况,例如此问题的范围。它会在立即窗口中报告(从VBA按Ctrl + G打开)。

我个人总是选择“更多数据”,几分钟的额外工作可以更容易地看到哪些流程一直很麻烦。


用法示例:

如果我们假装你正在运行的进程是MsgBox

Sub DemoProcedure()

    timeIt "msgbox1:Hi"
    MsgBox "hi"

    timeIt "msgbox2:Hello"
    MsgBox "hello"

    timeIt "msg3:Heya"
    MsgBox "heya"

    timeIt "msg4:Hola"
    MsgBox "hola"
    timeIt ""         '<-- call with empty string to get the last time

End Sub

示例输出:

这会在立即窗口中生成输出,如:

-> msgbox1:Hi:       1.2 seconds
-> msgbox2:Hello:    1.1 seconds
-> msg3:Heya:      222.7 seconds
-> msg4:Hola:        0.4 seconds

很明显,我的msg“heya”程序是这里的问题。 :)


记录到表格

要将计时数据记录到本地表(以及立即窗口),请取消注释代码中的三个相关行并添加如下所示的表:

它将记录数据,如:


Tips to improve Access database performance

  1. 使用紧凑和修复
  2. 仅加载您需要的内容
  3. 确保所有表都有主键
  4. 通过添加二级索引进行优化
  5. 拆分数据库

有关这些来自source的更多信息。

...还有许多其他在线文章,提供有关改善访问性能的建议。

底线是它不可能只是一个问题。 “整个数据库健康”包括自下而上的超组织是至关重要的。在相同的情况下,成本:效益比甚至可以证明重新开始并重新设计一个“完美”的数据库,从绘图板开始(字面意思!)......

祝好运!


0
投票

我会先建立一个测试表格。

将表单绑定到“大”sql表。

然后试试这段代码:

Docmd.OpenForm“frmTest”,,,“id = 10”

在上面,将“10”替换为表的已知PK id。

这种形式加载速度慢还是快?

如果表单加载缓慢,那么我们可以确定表单的“缓慢”加载不是由于过多的数据或从表中提取太多数据。请记住,上面的命令只会从表中提取ONE记录。

那么这个测试形式是慢还是快?

如果表单速度很快,那么我们就可以消除数据连接问题,或者只是花费很多时间访问它。

如果表单加载速度慢,那么数据优化不是您的问题。

上述测试需要30秒进行烹饪和测试。只需创建绑定表单,保存它,然后敲击ctrl-g,并在调试窗口中输入上面的docmd.OpenForm。

如果上面的速度很快,那么贪婪形式就会导致过多的数据拉扯。

甚至更好的方法是使用一个链接表和一个测试表创建一个独立的测试accDB。再次,测试 - 是快还是慢?

如果表单加载速度很快,那么我们回到实际的应用程序有错误。例如,不存在的打印机,或链接到OTHER mdb / accdb文件是我要看的下一个问题(如果测试表快速运行)。

另一个问题是你没有提到SQL服务器的位置,并且是这种连接中涉及的某种类型的“wan”(比如在网站上运行的sql,或者在你使用的其他一些建筑物/位置) WAN而不是LAN连接到该数据库。

我定期点击具有300多万行的sql server表,尽管表格尽管是直接绑定到那个大表,我们看到并找到负载不到1秒。

© www.soinside.com 2019 - 2024. All rights reserved.