在MS Access 2010中更新查询会耗尽系统资源

时间:2014-07-10 17:46:22

标签: sql sharepoint access-vba

由于我无法控制的原因,我们使用Access 2010更新链接的SharePoint列表,以使它们与我们的CMDB保持同步。我们以CSV格式从CMDB获取报告,并将它们链接到Access。然后,我们使用Access VBA和预定义查询的组合来添加新数据,或者更新或软删除现有数据。特别是一个列表导致问题。具体来说,插入/软删除似乎工作,但Access在运行更新查询时耗尽资源和崩溃。拉起资源监视器显示内存使用量随着应用程序的运行而不断增加,并且当〜1.6 GB或RAM分配给它时,Access最终会失败(在具有6 GB交换文件的4 GB计算机上,Windows 7 64位,但是32位访问)。

除VBA代码外,我还使用了两个查询。一个查询检索结果集,该结果集允许我确定要更新SharePoint列表中的哪一行(如果有),而另一个查询则标识报表中的哪些列更新SharePoint列表中的相应列,链接报表之间的连接条件和相应的列表,以及要更新的SP中的行,由其组合键标识。我认为这是相当标准的东西。

由于SharePoint列表具有关联的工作流,因此我们必须使用此方法(或一种基本相似的方法)。我们发现,如果我们编写SQL来执行标准的集合类型更新,则更新发生得太快,会导致Sharepoint的工作流引擎过载并导致工作流失败。

我尝试过多种替代技术:

  • 使用记录集编辑/更新序列而不是查询/执行 如下所示。这会更快地消耗内存,并且会飙升 CPU为26%对12%。
  • 如下面的VBA代码所示,我已尝试每次关闭并重新打开查询 100行,以及使用事务。两种技术都没有结果 改善。
  • 我尝试过禁用然后重新启用和扩展Access'
    SharePoint缓存机制,但没有成功。
  • 我尝试过使用参数化查询。这种技术不起作用 因为我们必须更新一些备忘录字段,并查询参数max 超过255个字符。
  • 运行数据库compact / repair不会释放已分配的内存。

这是执行查询的VBA代码:

 Private Sub runUpdt()
   Dim oQdfUpdt As DAO.QueryDef
   Dim oRs As DAO.Recordset
   Dim oWrkSpc As DAO.Workspace
   Dim strmsg As String

   On Error GoTo Handler

   logMsg "Entering method runUpdt in class clsAppFsFin"
   Debug.Print "Entering method runUpdt in class clsAppFsFin", Now()

   Set oRs = CurrentDb.QueryDefs("slctAppFsFinRowsForUpdt").OpenRecordset(dbOpenDynaset, dbReadOnly)
   Set oQdfUpdt = CurrentDb.QueryDefs("updtAppFsFin")
   Set oWrkSpc = DBEngine.Workspaces(0)

   Do While (Not oRs.EOF)
      oWrkSpc.BeginTrans

      If (isUpdated(oRs)) Then
         oQdfUpdt.Parameters("CHGTXT") = "System Change"
         oQdfUpdt.Parameters("CID") = oRs.Fields("RYCID")
         oQdfUpdt.Execute

         ' inserts a row into the flg_is_updt table
         oFlgUpdt.insFlgIsUpdt oRs.Fields("RYAID")
      ElseIf (oRs.Fields("SPCTX") <> "System NoChange") Then
         oQdfUpdt.Parameters("CHGTXT") = "System NoChange"
         oQdfUpdt.Parameters("CID") = oRs.Fields("RYCID")
         oQdfUpdt.Execute

         ' inserts a row into the flg_is_updt table
         oFlgUpdt.insFlgIsUpdt oRs.Fields("RYAID")
      End If

      oWrkSpc.CommitTrans

      If ((oRs.AbsolutePosition Mod 100 = 0) And (oRs.AbsolutePosition > 0)) Then
         strmsg = "Updated " & oRs.AbsolutePosition & " rows. Class: clsAppFsFin, Method: runUpdt."
         Debug.Print strmsg, Now()
         logMsg strmsg

         Dim curFSCID As String

         curFSCID = oRs.Fields("RYCID")
         oRs.Close
         Set oRs = Nothing

         oQdfUpdt.Close
         Set oQdfUpdt = Nothing

         Set oRs = CurrentDb.QueryDefs("slctAppFsFinRowsForUpdt").OpenRecordset
         Set oQdfUpdt = CurrentDb.QueryDefs("updtAppFsFin")

         oRs.FindFirst "RYCID = '" & curFSCID & "'"
      End If

      ' sleep .1 seconds to avoid overloading the upstream workflow
      Sleep SLEEPTIMEINMILLIS
      oRs.MoveNext
   Loop

   strmsg = "Final update count: " & oRs.RecordCount & " rows. Class: clsAppFsFin, Method: runUpdt."
   logMsg strmsg
   Debug.Print strmsg, Now()

   oRs.Close
   oQdfUpdt.Close

   Set oRs = Nothing
   Set oQdfUpdt = Nothing

   Debug.Print "Exiting method runUpdt in class clsAppFsFin", Now()
   logMsg "Exiting method runUpdt in class clsAppFsFin"
   Exit Sub
Handler:
   oWrkSpc.Rollback

   Debug.Print Err.Number, Err.Description
   logError Err.Number, Err.Description
End Sub

以下是VBA代码执行的选择和更新查询

选择查询:

SELECT          APFF.[App ID]                                   AS SPAID,
                APFF.Server                                     AS SPHST,
                APFF.Directory                                  AS SPDIR,
                RAppAH.AppID                                    AS RYAID,
                RAppAH.Host                                     AS RYHST,
                RAppAH.FSCID                                    AS RYCID
                <
                 snip
                >
FROM           (AppCert
INNER JOIN      AppFileSystemFin                                AS APFF
ON              AppCert.[App ID]                                 = APFF.[App ID])
LEFT JOIN       RAppAH
ON              APFF.FSCID                                       = RAppAH.FSCID
WHERE           APFF.FSCID                                       = [RAppAH].[FSCID]
           AND  AppCert.State                                    = "8 - Complete"
           AND  RAppAH.FSCID                                    IS NOT NULL
           AND  APFF.[Change In SoR - Text]                     <> "System Remove"
ORDER BY        APFF.ID;

更新查询:

UPDATE     AppFileSystemFin
INNER JOIN RAppAH
ON         AppFileSystemFin.FSCID     = RAppAH.FSCID
SET        AppFileSystemFin.Server    = [RAppAH].[Host],
           AppFileSystemFin.Directory = [RAppAH].[Directory],
           <
            snip
           >               
WHERE      AppFileSystemFin.ID        = [ID];

1 个答案:

答案 0 :(得分:0)

问题现已解决。在上面显示的更新查询中,行:

在哪里AppFileSystemFin.ID = [ID];

未引用Sharepoint的系统生成的ID列。相反,它指的是我们必须使用的内部生成的键字段,以便能够在列表之间执行SQL连接操作。

查询已更新为使用SharePoint生成的ID列。这个次要更新解决了内存分配问题,反过来又允许更新更快地进行 - 现在只需要前一个运行时的大约三分之一来完成执行。