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

时间:2018-09-17 11:35:38

标签: sql ms-access access-vba

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

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

我有一个具有后端sql服务器的Access 2016数据库,该数据库用于所有数据库上的计算。该数据库用于存储多个作业数据,每个用户都可以在作业之间切换以查看数据。

在计算方面相当复杂,但是数据库本身的大小仅为15mb。始终需要花费10秒钟来加载每种表单,从用户的角度来看这几乎是无法使用的。

是否有关于加速数据库的最佳方法的建议?它在远程服务器上,每个用户都登录到远程服务器以使用它。因此,没有数据库分裂或其他任何事情。我再次在线阅读这些文章,例如http://www.granite.ab.ca/access/performancefaq.htmhttp://www.granite.ab.ca/access/performanceldblocking.htm

但是,正如几年前所讨论的那样,我只是想知道是否存在一种更新的方法来使数据库运行更快。

关于, 迈克尔

2 个答案:

答案 0 :(得分:3)

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

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

实际上,它更有可能增加,因为计算仍然可以通过运行查询的任何计算机来完成(我假设您的前端,除非您进行了一些精美的编码来执行SQL Stored后端的程序等,并从那里检索数据。

...所以现在仍然是同一台机器像以前一样执行计算-但现在数据必须从服务器中拉出到每个本地计算机当您运行查询时(而不是之前),数据已经是本地的。


普通罪犯

没有看到您的数据库,除了猜测,其他人无能为力,而我的猜测是您有多个设计欠佳的查询,这些查询填充了正在打开的每种表格。

...可能是相同查询的各种化身一遍又一遍吗?例如,根据我的经验,一个常见的问题是:是否有一个组合框列出受各种条件限制的员工姓名或其他数据?也许必须为每种表单运行类似的查询?可能对几种形式中的每一种都有几种查询?

需要简化类似重复的工作量,具体如何处理取决于您的情况。对于上面的示例,每当员工列表更改时,都可以生成一个静态表,该表仅包括应该包含在组合框中的名称。该表可以存储在本地,从而可以替换几个重复查询,这些查询是在每个数据库打开几次后计算出来的。

另一个常见的错误是在查询中使用耗时的自定义函数,该查询必须针对数千条记录运行该函数。如果一个查询一次调用了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” 过程是这里的问题。 :)


登录到表

要将计时数据记录到本地表(以及即时窗口)中,请取消注释代码中的三个相关行,并添加一个类似于以下内容的表:

img

它将记录数据,例如:

img


提高Access数据库性能的提示

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

来自source的更多信息。

...在线上还有许多其他文章,其中对提高Access性能提供了建议。

最重要的是,这不可能是一个单一的问题。自下而上的包括整个组织在内的“整个数据库健康”至关重要。在相同的情况下,成本:收益比甚至可以证明是重新开始并重新设计“完美”数据库(从字面上开始)的合理性。

祝你好运!

答案 1 :(得分:0)

我首先要建立一个测试表格。

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

然后尝试以下代码:

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

在上面,用表的已知PK ID替换“ 10”。

此表格加载缓慢还是快速?

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

那么此测试表格是慢速还是快速?

如果表单很快,那么我们就可以消除数据连接问题,或者只需花点时间就可以访问。

如果表单加载缓慢,则数据优化不是您的问题。

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

如果上述操作很快,那么淫秽形式会导致提取过多的数据。

更好的办法是创建一个仅包含一个链接表和一个测试表单的独立测试accDB。再次测试-是快还是慢?

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

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

我定期命中具有3+百万行的sql服务器表,尽管该表格直接绑定到了那个大表,但我们发现负载小于1秒。