加速访问数据库

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

我想知道是否有人对加速访问数据库中的查询有任何建议?如果这是一篇冗长的帖子,我深表歉意,但是设置有点与众不同....

我正在创建一个Access数据库来报告从大型机系统收集的事件统计信息。我们当前使用的大型机调度程序(ZEKE)并不完全具有强大的报告功能,因此我正在导出每日事件数据以进行报告。我还有一个单独的主列表(它是静态列表,不会定期更改),其中列出了所有单个应用程序,包括应用程序代码(这是生产运行的命名标准)和名称特定应用程序的程序员,协调员,经理,业务部门等。设置数据库后,用户可以按任何字段,应用程序代码,程序员,协调员等进行搜索。选择要搜索的生产中心(有5个)或默认为全部,并选择所有日期,单个日期,或日期范围。该查询通过获取搜索参数并从应用程序代码或人员开始工作。它在表中搜索应用程序,并将所有相关记录复制到临时表中以进行报告。例如,如果我想查看应用程序协调员John Doe在过去一周中对他负责的所有应用程序发生了多少次故障,查询将把列出John Doe作为协调员的所有应用程序记录移至临时表。从那里开始,它在每个应用程序的临时表中移动,并在事件数据中搜索该应用程序代码下的事件,这些事件符合为日期,生产中心和事件类型(成功,失败或两者)输入的条件。将其移至最终报告的临时表,然后生成最终报告。

就目前而言,我的代码可以正常工作,并且完全按照我想要的去做,问题是,事件数据表当前为250万行(这是15天的数据),并且每天都在增长。我将后端放在网络上新创建的NAS驱动器上并进行了测试……它确实有效,但是当后端和前端在同一台计算机上时,需要2分钟才能运行的报告现在需要29分钟。将其放在网络上已经使它陷入了瘫痪。我想就如何设置搜索循环而言,我可能会遇到一些隧道问题,并且我想知道是否有人对简化查询的更好或更快速的方法提出了建议,以便它们可以通过网络加快速度。我在下面包含了我的代码。这确实可以正常工作,并且可以按预期生成报告,但是如果有其他查询方法或简化方法,我将非常感谢您提供任何建议。我包含的代码是从报告条件选择表单运行并根据用户输入运行报告的代码。

'this macro will generate a report based on multiple input criteria.
'this report allows the user to slect:
'       date range, single date or all dates
'       type of events: Abends, Successes or both
'       centers to pull data from: OCC,QCC,BCC,ITS,DAIN, or ALL centers
'       The type of data to report on: App code, App Coordinator, Custodian, L3, L4 or L5
'Once the user has selected all of the required data and fields, the report will be generated
'based on the selection criteria.

'we begin by defining the active database as the currently open database
Dim db As DAO.Database
    Set db = DBEngine(0)(0)


On Error GoTo ErrorHandler

'Now we designate the variables which will be used in this macro

   Dim strSQ1 As String
   Dim strSQ2 As String
   Dim strSQ3 As String
   Dim strSQ4 As String
   Dim appl As String
   Dim evstatus As String
   Dim appletype As String
   Dim fullapp As String
   Dim length As Long
   Dim iipmname As String
   Dim iipmcoor As String
   Dim fullappnm As String
   Dim fullappcoor As String
   Dim kinddate As String
   Dim coor As String
Dim cust  As String
Dim appL3  As String
Dim appL4  As String
Dim appL5 As String

   Dim ctrOCC As String
   Dim ctrMTL As String
   Dim ctrBCC As String
   Dim ctrITS As String
   Dim ctrDAIN As String



'We will start by setting some default values

'We will ste the default values for center selection.
'We start by searching for terms we know are not there, then change them to
'valid search terms if the center is selected.

ctrOCC = "notOCC"
ctrMTL = "notMTL"
ctrBCC = "notBCC"
ctrITS = "notITS"
ctrDAIN = "notUSWM"
fullapp = "*"

'First we determine which event types the user wants to look for

state = Me![opt-status].Value

If state = 1 Then
evstatus = " [ev-status] = 'AEOJ'"
ElseIf state = 2 Then
evstatus = " [ev-status] = 'EOJ'"
ElseIf state = 3 Then
evstatus = " ([ev-status] = 'EOJ' OR [ev-status] = 'AEOJ')"
End If

'MsgBox "Event status pulled is:.. " & evstatus & "."

' Next up we will configure the date parameters based on the user input

If [grp-datesel] = 1 Then
Sdte = "1"
Edte = "9999999"
kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " "
End If

If [grp-datesel] = 2 Then
'error handling
If IsNull(Me.[sel-onedate]) Then
MsgBox "You have not entered a date to search....please try again."
Me.[sel-onedate] = Null
Me.[sel-onedate].SetFocus
Exit Sub
End If
'end of error handling

Dim currdte As Date
currdte = Me![sel-onedate].Value
currjul = Format(currdte, "yyyyy")
daycurr = CDbl(currjul)

Sdte = daycurr
Edte = daycurr
kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " "
End If

If [grp-datesel] = 3 Then

'error handling
If IsNull(Me.[sel-Sdate]) Or IsNull(Me.[sel-Edate]) Then
MsgBox "You Must enter a start and end date for the search....please try again."
Me.[sel-Sdate] = Null
Me.[sel-Edate] = Null
Me.[sel-Sdate].SetFocus
Exit Sub
End If
'end of error handling

Dim startdte As Date
Dim enddte As Date
startdte = Me.[sel-Sdate].Value
enddte = Me.[sel-Edate].Value

startjul = Format(startdte, "yyyyy")
endjul = Format(enddte, "yyyyy")
Sday = CDbl(startjul)
Eday = CDbl(endjul)

Sdte = Sday
Edte = Eday

'MsgBox "start date is " & Sdte & " and end date is " & Edte & "."

'check that dates are in proper chronological order
If Sdte > Edte Then
MsgBox "The start Date you entered is after the end date....please try again."
Me.[sel-Sdate] = Null
Me.[sel-Edate] = Null
Me.[sel-Sdate].SetFocus
Exit Sub
End If
'keep going if it's all good

kinddate = "[ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & " "
End If

MsgBox "Date used is:.. " & kinddate & "."

'Now lets look at center selection

If [chk-allctr].Value = True Then
ctrOCC = "OCC"
ctrMTL = "MTL"
ctrBCC = "BCC"
ctrITS = "ITS"
ctrDAIN = "USWM"

End If

If [chk-OCC].Value = True Then
ctrOCC = "OCC"
End If
If [chk-MTL].Value = True Then
ctrMTL = "MTL"
End If
If [chk-BCC].Value = True Then
ctrBCC = "BCC"
End If
If [chk-RTF].Value = True Then
ctrITS = "ITS"
End If
If [chk-DAIN].Value = True Then
ctrDAIN = "DAIN"
End If

'Error handling if no center is selected
If [chk-OCC].Value = Flase Then
If [chk-MTL].Value = Flase Then
If [chk-BCC].Value = Flase Then
If [chk-RTF].Value = Flase Then
If [chk-DAIN].Value = Flase Then
MsgBox "You have not selected a center to search search....please try again."
Me.[chk-allctr].SetFocus
Exit Sub
End If
End If
End If
End If
End If
'end of error handling

'MsgBox "centers used are: Chr(10) " & ctrOCC & " Chr(10) " & ctrBCC & " Chr(10) " & ctrMTL & " Chr(10) " & ctrITS & " Chr(10) " & ctrDAIN & " For this run"

'All good so far, now we will parse the application code if an
'application code report is selected

appl = "*"

If [opt-criteria].Value = 1 Then
'error handling
If IsNull(Me.[sel-appcode]) Then
MsgBox "You have not entered an application code to search....please try again."
Me.[sel-appcode] = Null
Me.[sel-appcode].SetFocus
Exit Sub
End If
'end of error handling
End If
If [opt-criteria].Value = 1 Then

appl = Me![sel-appcode].Value
End If

'trust = "no"
'If Mid(appl, 3, 2) = "RT" Then trust = "yes"

'length = Len(appl)
'If length = 2 Then appltype = "short"
'If length = 3 Then appltype = "long"

'If appltype = "short" Then fullapp = "" & appl & "00"
'If appltype = "long" Then fullapp = "" & appl & "0"

'If trust = "yes" Then fullapp = appl

'End If

fullapp = appl

'MsgBox "App to use is: " & appl & " fullapp code is " & fullapp & "."


'Now we set values if names are used

coor = "*"
cust = "*"
appL3 = "*"
appL4 = "*"
appL5 = "*"

If [opt-criteria].Value = 2 Then
'error handling
If IsNull(Me.[sel-coor]) Then
MsgBox "You have not entered a Coordinator to search....please try again."
Me.[sel-coor] = Null
Me.[sel-coor].SetFocus
Exit Sub
End If
'end of error handling

coor = Me![sel-coor].Value
'MsgBox "Coordinator report selected for: " & coor & "."
End If

If [opt-criteria].Value = 3 Then
'error handling
If IsNull(Me.[sel-custodian]) Then
MsgBox "You have not entered a Custodian to search....please try again."
Me.[sel-custodian] = Null
Me.[sel-custodian].SetFocus
Exit Sub
End If
'end of error handling
cust = Me![sel-custodian].Value
'MsgBox "Custodian report selected for: " & cust & "."
End If

If [opt-criteria].Value = 4 Then
'error handling
If IsNull(Me.[sel-L3]) Then
MsgBox "You have not entered an L3 to search....please try again."
Me.[sel-L3] = Null
Me.[sel-L3].SetFocus
Exit Sub
End If
'end of error handling

appL3 = Me![sel-L3].Value
'MsgBox "L3 report selected for: " & appL3 & "."
End If

If [opt-criteria].Value = 5 Then
'error handling
If IsNull(Me.[sel-L4]) Then
MsgBox "You have not entered an L4 to search....please try again."
Me.[sel-L4] = Null
Me.[sel-L4].SetFocus
Exit Sub
End If
'end of error handling

appL4 = Me![sel-L4].Value
'MsgBox "L4 report selected for: " & appL4 & "."
End If

If [opt-criteria].Value = 6 Then
'error handling
If IsNull(Me.[sel-L5]) Then
MsgBox "You have not entered an L5 to search....please try again."
Me.[sel-L5] = Null
Me.[sel-L5].SetFocus
Exit Sub
End If
'end of error handling

appL5 = Me![sel-L5].Value
'MsgBox "L5 report selected for: " & appL5 & "."
End If

'Most of these reports take a while to build with this macro, so to make sure the user
'knows that the macro is still working, we didsplay a splash screen. It's cute and has
'hamsters, cause everyone loves hamsters.

DoCmd.OpenForm "PlsWaitFrm", acWindowNormal
[Forms]![PlsWaitFrm].Repaint



'All of out criteria values are now selected.  We can move on to pulling data from the tables.
'We start by populating the IIPM table with the information that we require for applications.

strSQ1 = "DELETE * from [tbl-RPT-IIPM] "
db.Execute strSQ1

strSQ2 = "INSERT INTO [tbl-RPT-IIPM] " & _
         "SELECT * FROM [tbl-IIPM] " & _
         "WHERE (([AppCode] like '" & fullapp & "')" & _
         "AND ([AppCoordinator] like '" & coor & "') " & _
         "AND ([AppCustodian] like '" & cust & "') " & _
         "AND ([L3] like '" & appL3 & "') " & _
         "AND ([L4] like '" & appL4 & "') " & _
         "AND ([L5] like '" & appL5 & "')) "
db.Execute strSQ2

'MsgBox "made it past the populate of rpt-iipm"


'Now we have populated the IIPM report table, it's time to populate the event report table.
'We will loop through all fields in the IIPM report table and pull information for each
'application code.

strSQ3 = "DELETE * from [tbl-EVENTREPORT] "
db.Execute strSQ3

Dim rs As DAO.Recordset

Set db = CurrentDb
Set rs = db.OpenRecordset("tbl-RPT-IIPM") 'this opens the IIPM report table just populated

'populate the table
rs.MoveLast
rs.MoveFirst

Do While Not rs.EOF
'we will execute these action against the selected record.

'first step - parse the application code to display the full application code

appl = rs![AppCode].Value
length = Len(appl)
If length = 1 Then appl = "" & appl & "00"

rptdelin = Mid(appl, 3, 1)

rptcode = Mid(appl, 1, 3)
If rptdelin = "0" Then rptcode = Mid(appl, 1, 2)
If rptdelin = "R" Then rptcode = "RT" & Mid(appl, 1, 2) & ""

'MsgBox "searching for: " & rptcode & "."

applist = applist & "," & appl

strSQ4 = "INSERT INTO [tbl-EVENTREPORT] " & _
         "SELECT * FROM [tbl-EVENT DATA] " & _
         "WHERE (([ev-jobname] LIKE '?" & rptcode & "*') " & _
         "AND (([ev-ctr] = '" & ctrOCC & "')" & _
         "OR ([ev-ctr] = '" & ctrMTL & "')" & _
         "OR ([ev-ctr] = '" & ctrBCC & "')" & _
         "OR ([ev-ctr] = '" & ctrITS & "')" & _
         "OR ([ev-ctr] = '" & ctrDAIN & "'))" & _
         "AND (" & kinddate & ") " & _
         "AND " & evstatus & ")"

db.Execute strSQ4

 'now we're done with this report, we move on to the next

   rs.MoveNext             'press Ctrl+G to see debuG window beneath
Loop

'END OF LOOPING CODE

'MsgBox "made it past the looping"

'Now we have completed populating the table that the report will be based on.
'Next step is to gather master statistics to produce abend and success percentages.

totfail = DCount("[ev-status]", "tbl-EVENTREPORT", "[ev-status] = 'AEOJ'")
totsucc = DCount("[ev-status]", "tbl-EVENTREPORT", "[ev-status] = 'EOJ'")

Dim allabend As Long
Dim allsucc As Long

allabend = DCount("[ev-status]", "[tbl-EVENT DATA]", "[ev-status] = 'AEOJ' AND ([ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & ")")
allsucc = DCount("[ev-status]", "[tbl-EVENT DATA]", "[ev-status] = 'EOJ' AND ([ev-date] >= " & Sdte & " AND [ev-date] <= " & Edte & ")")

Dim pctabend As Long
Dim pctsucc As Long

pctabend = (totfail / allabend) * 100
pctsucc = (totsucc / allsucc) * 100

'Now we will generate the reports for display based on what type of report was selected
'by the user in the initial form.

'Before we open the report, we will close the splash screen
DoCmd.Close acForm, "PlsWaitFrm", acSaveNo

'Now we open the report

If [opt-criteria].Value = 1 Then

fullappnm = DLookup("AppName", "tbl-RPT-IIPM", "AppCode = '" & fullapp & "' ")
fullappcoor = DLookup("AppCoordinator", "tbl-RPT-IIPM", "AppCode = '" & fullapp & "' ")



DoCmd.OpenReport "rpt-APPLREPORT", acViewReport

[Reports]![rpt-APPLREPORT]![rpt-appcode].Value = fullapp
[Reports]![rpt-APPLREPORT]![rpt-appname].Value = fullappnm
[Reports]![rpt-APPLREPORT]![rpt-appcoor].Value = fullappcoor
[Reports]![rpt-APPLREPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-APPLREPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-APPLREPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-APPLREPORT]![rpt-succpct].Value = pctsucc

End If

If [opt-criteria].Value = 2 Then

DoCmd.OpenReport "rpt-COORREPORT", acViewReport

[Reports]![rpt-COORREPORT]![rpt-appcode].Value = applist
[Reports]![rpt-COORREPORT]![rpt-appcoor].Value = coor
[Reports]![rpt-COORREPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-COORREPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-COORREPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-COORREPORT]![rpt-succpct].Value = pctsucc

End If

If [opt-criteria].Value = 3 Then

DoCmd.OpenReport "rpt-CUSTREPORT", acViewReport

[Reports]![rpt-CUSTREPORT]![rpt-appcode].Value = applist
[Reports]![rpt-CUSTREPORT]![rpt-appcoor].Value = cust
[Reports]![rpt-CUSTREPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-CUSTREPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-CUSTREPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-CUSTREPORT]![rpt-succpct].Value = pctsucc
End If

If [opt-criteria].Value = 4 Then

DoCmd.OpenReport "rpt-L3REPORT", acViewReport

[Reports]![rpt-L3REPORT]![rpt-appcode].Value = applist
[Reports]![rpt-L3REPORT]![rpt-appcoor].Value = appL3
[Reports]![rpt-L3REPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-L3REPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-L3REPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-L3REPORT]![rpt-succpct].Value = pctsucc
End If


If [opt-criteria].Value = 5 Then

DoCmd.OpenReport "rpt-L4REPORT", acViewReport

[Reports]![rpt-L4REPORT]![rpt-appcode].Value = applist
[Reports]![rpt-L4REPORT]![rpt-appcoor].Value = appL4
[Reports]![rpt-L4REPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-L4REPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-L4REPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-L4REPORT]![rpt-succpct].Value = pctsucc
End If

If [opt-criteria].Value = 6 Then

DoCmd.OpenReport "rpt-L5REPORT", acViewReport

[Reports]![rpt-L5REPORT]![rpt-appcode].Value = applist
[Reports]![rpt-L5REPORT]![rpt-appcoor].Value = appL5
[Reports]![rpt-L5REPORT]![rpt-abendtot].Value = totfail
[Reports]![rpt-L5REPORT]![rpt-succtot].Value = totsucc
[Reports]![rpt-L5REPORT]![rpt-abdpct].Value = pctabend
[Reports]![rpt-L5REPORT]![rpt-succpct].Value = pctsucc
End If



ErrorHandler:
If Err.Number = 7874 Then
Resume Next 'Tried to delete a non-existing table, resume
End If
End Sub
'''

Again, I very much appreciate any thoughts. 

-Gord


database vba ms-access ms-access-2016
2个回答
0
投票

首先,您需要找出瓶颈所在,所以我建议在代码中放置一些Debug.Print Now语句,以使您了解问题的根源。

我想您花费的大部分时间中有两个过程是您正在执行的DELETE / INSERT语句。

我建议您而不是这样做,而是着眼于规范化数据库,然后创建一个提供所需信息的查询。

此外,通过直接从查询而不是临时表运行报告意味着您不必担心删除/插入会造成数据库膨胀的问题。

如果您真的坚持要保留此过程,请考虑删除表[tbl-RPT-IIPM],然后重新创建它,而不是删除记录。并考虑删除插入之前的索引,然后再将它们添加回去,因为索引会减慢插入速度,但显然会加快搜索和连接的速度。

此外,当您将数据插入[tbl-RPT-IIPM]时,您正在使用([L3] like '" & appL3 & "'),它与([L3]='" & appL3 & "')相同,但速度较慢。

[将数据插入[tbl-EVENTREPORT]时,是在遍历记录集时进行的-使用INSERT SQL语句可能会更快。

问候,


0
投票

Applecore,首先,感谢您的见解。不幸的是,由于数据处理方式的本质,我不确定其中的某些方法可以实现。我使用了debug.print语句来更好地了解时间安排。

您是正确的,INSERT语句引起了我最多的问题,而第二个问题最多。删除几乎立即完成,没有问题。这是事件数据的第二次插入,正在减慢它的速度。

自从我开始思考如何更有效地宣传和建立更好的关系以来,我就一直在思考这个问题,但我受阻。我的问题是,事件表和事件表之间的数据“相关”,但在数据方面并不清楚。没有复杂的计算就无法确定关系。例如,应用程序数据的唯一部分是应用程序代码。他们总是独一无二的。单个应用程序协调器可以分配数十个代码,保管人,L3,L4等也可以分配给每个代码。每个事件都与一个应用程序相关,但是,没有导出任何特定字段来告诉应用程序代码,它是通过解析事件名称(是的,听起来很陈旧)。事件命名标准是标准大型机8个字符名称:。例如PGRD1234-生产作业,GRD应用程序,1234作为指示符。因此,要确定作业与哪个应用程序相关,我将获取应用程序代码,然后选择带有通配符的LIKE。我知道它不是100%准确,但是要使用通配符,我似乎被LIKE困住了。我无法使用通配符使'='有效。你可以吗?

[您还提到了“将数据插入[tbl-EVENTREPORT]时,您在遍历记录集时正在执行此操作-使用INSERT SQL语句可能会更快。”我不知道你在说什么。。很抱歉。我不明白我的意思。我认为这就是我现在正在做的。我使用IIPM表获取需要提取的应用程序代码的列表,然后遍历该记录集以仅提取那些应用程序的所有事件数据。由于数据之间没有直接关联,因此我无法想到另一种方法。

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