不断增长的 MS Access 文件大小问题

Posted

技术标签:

【中文标题】不断增长的 MS Access 文件大小问题【英文标题】:Growing MS Access File Size problem 【发布时间】:2009-01-16 16:24:44 【问题描述】:

我有一个大型 MS Access 应用程序,在 VBA 代码中进行了大量计算。当我运行它时,它最终由于文件大小过大而崩溃。有很多中间表和查询创建并随后删除,但 Access 不会回收空间。我已经努力关闭所有中间记录集并将所有临时对象设置为空,但没有任何帮助。我可以让我的代码运行的唯一方法是运行它的一部分,停止并修复/压缩文件,然后重新启动代码。

没有更好的办法吗?

谢谢

【问题讨论】:

【参考方案1】:

您应该能够在您的 VBA 代码中运行压缩函数。

我很久以前在做访问工作时,将下面的 sn-p 加入书签。

Public Sub CompactDB() 
    CommandBars("Menu Bar").Controls("Tools").Controls("Database utilities").Controls("Compact and repair database...").accDoDefaultAction 
End Sub 

你可以把它放在你的代码中来绕过它。

注意:如果您遇到这些类型的扩展问题,您还可以考虑扩展为更大的数据库系统。

【讨论】:

我会注意到压缩和修复工具有时会产生损坏的数据库(不可读)。建议您在运行该工具之前始终备份您的数据库。在我看来,从代码自动运行它是一项高风险的操作。 如果你有一个拆分数据库并且后端增长,这将如何实现?【参考方案2】:

您处理的是什么尺寸的?崩溃时的错误代码是什么?如果仅仅是因为文件“太大”,我会感到惊讶,但我想有一个限制。从您对所有临时材料的描述中可以看出,设计改进可能会有所帮助。

编辑:我希望您意识到用其他东西替换数据库并非易事——即使您尝试保留 mdb 中除了表之外的其他任何东西。 Access 查询定义是唯一的,Access SQL 是非标准的,您基本上可以重新开始。

我见过的大多数 Access 应用程序都有很多重构的机会;如果 a) 您了解逻辑和业务规则,并且 b) 您对 Access 编程有扎实的了解,这通常并不难。但对于任何替代方案来说,这或多或少都是正确的。如果我是你,而你在这两个方面都有点不足,也许你可以得到一些帮助。但我会先尝试拯救 Access 应用程序。

还有来自另一张海报的关于将表移动到一个或多个附加的 MDB 中的建议。一般来说,这是一种可靠的、经过充分验证的技术。但首先我要弄清楚问题的真正原因是什么。

【讨论】:

我不同意你的观点。我已经将一些相当大的 MS Access DB 移到了 MS SQL 上,没有出现大问题(不,这不是微不足道的);但绝大多数查询定义等无需修改即可工作(特别是如果它们链接到 Access 数据库中的 SQL 表)。你没有重新开始,【参考方案3】:

我会将数据推送到 MS SQL(永久数据和中间表);代码部分暂时可以留在MS Access中。

这解决了两个大问题:

    数据本质上会更加稳定/可靠(我无法告诉您我的 MS Access 数据库损坏了多少次)。 您的 Access 数据库不会增长/变化太大(一旦所有代码都运行和编译,它应该会达到平衡)。

这两者都意味着不再需要压缩/修复数据库;您可以获得 MS SQL 的免费版本(Express 版),这并不难。

【讨论】:

【参考方案4】:

如果你不想切换到 SQL Express 或类似的,你可以挖掘以下想法:

为所有临时表打开另一个“外部”访问数据库(mdb 文件),这样您就可以将所有临时数据放在外部文件中,在您关闭应用程序时丢弃 mdb 文件。然后,您将在代码中操作“currentDb”对象和您在启动时构建并通过 jet、OLEDB 或 ODBC 连接连接到的另一个数据库 将永久表与代码分开,并在需要时将数据带入本地客户端界面以构建临时表。例如,这可以通过使用“DoCmd.transferDatabase acLink”将外部数据库链接到本地​​/客户端文件来完成。这也可以通过 OLEDB 连接连接到永久数据、打开所需的记录集并将它们在本地保存为 XML 文件来完成。还有许多其他解决方案可以在这里实现。

【讨论】:

【参考方案5】:

关于 Jet 文件大小的现状对我来说是无穷无尽的问题。

我目前正在查看 Access 数据库 A 中的一段我自己的 VBA 代码,因为它使用 ADO 对 Access 数据库 B 上的表执行一系列单记录字段更新(通过可更新的-数据库 A) 中的查询参考。单个字段是 CHAR(8)。每进行 4 次更新,数据库 B 就会增长大约 8 KB。没有什么好的借口。文件大小的增加会严重降低性能;随着每个文件的增长,更新速度从大约每秒一次(在大约 30-40K 记录的表中,使用单记录 SQL 查找并且没有任何索引)到每 5-10 秒一次。 现在,我承认,在运行此更新代码之前,我已经压缩/修复了数据库 B;也许如果我没有这样做,表现就不会这么糟糕。如果更新的目标字段是,比如说,键入备忘录,那么我会预料到这一点。但是对一个 CHAR() 字段进行更新并得到这个结果是不合理的。

以上大部分内容(对任何一种解决方案都没有特别的批评)对于使用相对永久的业务应用程序安排(始终与相同的目标数据库对话)的应用程序来说似乎是有效的解决方案。我的不是这样。 . .我无法更改目标数据库(数据库 B),因为它是由供应商的工具生成和使用的,我们使用该工具从他们的应用程序中导出和导入数据。

我理解并赞扬上述作者提出解决用户问题的方法。但是,当糟糕的软件设计/实施妨碍用户按照用户期望的方式使用产品时,我不能让它站稳脚跟。

【讨论】:

对我来说,承认一次更新一条记录是一个危险信号。你确定不能用批量 SQL UPDATE 来完成吗?其次,这里没有惊喜。 Jet/ACE 将记录存储在可变长度字段中。更改非固定长度字段中的数据将更改记录的长度,并需要在不同的数据页中重写它。这完全是设计使然,与曾经存在的任何数据库引擎并没有太大区别(除了那些磁盘空间比 90 年代初设计 Jet 时更受限制的日子)。【参考方案6】:

我不是 MVP,但 Google 找到了这些。也许他们会帮助你:

http://www.mvps.org/access/general/gen0041.htm http://forums.devarticles.com/microsoft-access-development-49/compact-database-via-vba-24958.html

【讨论】:

【参考方案7】:

不幸的是,当您变得太大时,MS Access 会出现问题 - 我认为访问数据库的最大大小为 2GB。

您可以考虑迁移到 Sql Express、VistaDB 等。

【讨论】:

2GB 限制是有道理的,但它可能不是访问限制,而是操作系统限制。也就是说,由于 access 将其数据存储在单个文件中,操作系统上 2GB 的文件大小限制可能是故障点。 我不知道有 2GB 文件大小限制的任何最新版本的 Windows。确实,它不是 Access 限制——它是 Jet 限制,它是硬连线到 Jet 中的。 迟来的附录:某些文件系统,如 FAT32,有 2GB 的文件大小限制。但是没有任何人在 Windows 上使用 FAT32 了——随着 Windows 版本的 Win9x 系列的消亡。【参考方案8】:

根据http://office.microsoft.com/en-us/access/HP051868081033.aspx,Access 2003 和 2007 有 2 GB 的限制。但是,很容易将部分或全部表移动到单独的 .mdb 文件中,然后链接到这些表。无论如何,最好有两个文件,一个用于您的数据,一个用于所有宏、查询等。如果您的表格文件接近 2 GB 限制,您甚至可以拥有多个文件。

【讨论】:

【参考方案9】:

我遇到了类似的问题,即我的数据库在导入原始数据时膨胀。我决定使用数据库对象 (DAO) 创建临时数据库,导入数据,查询/修改临时数据库中的数据,通过 SQL 将其拉到原始数据库中,而不是常规地拆分数据库和压缩后端然后删除它。 YBase代码如下:

Sub tempAccessDatabaseImport()
    Dim mysql As String
    Dim tempDBPath As String
    Dim myWrk As DAO.Workspace
    Dim tempDB As DAO.Database
    Dim myObject

    'Define temp access database path
    tempPathArr = Split(Application.CurrentProject.Path, "\")
    For i = LBound(tempPathArr) To UBound(tempPathArr)
        tempDBPath = tempDBPath + tempPathArr(i) + "\"
    Next i
    tempDBPath = tempDBPath + "tempDB.accdb"

    'Delete temp access database if exists
    Set myObject = CreateObject("Scripting.FileSystemObject")
    If myObject.FileExists(tempDBPath) Then
        myObject.deleteFile (tempDBPath)
    End If

    'Open default workspace
    Set myWrk = DBEngine.Workspaces(0)

    'DAO Create database
    Set tempDB = myWrk.CreateDatabase(tempDBPath, dbLangGeneral)

    'DAO - Import temp xlsx into temp Access table
    mySQL = "SELECT * INTO tempTable FROM (SELECT vXLSX.*FROM [Excel 12.0;HDR=YES;DATABASE=" & RAWDATAPATH & "].[" & WORKSHEETNAME & "$] As vXLSX)"

    'DAO Execute SQL
    Debug.Print mySQL
    Debug.Print
    tempDB.Execute mySQL, dbSeeChanges

    'Do Something Else

    'Close DAO Database object
    tempDB.Close
    Set tempDB = Nothing

    myWrk.Close
    Set myWrk = Nothing

    'Delete temp access database if exists
    If myObject.FileExists(tempDBPath) Then
        'myObject.deleteFile (tempDBPath)
    End If
End Sub

【讨论】:

以上是关于不断增长的 MS Access 文件大小问题的主要内容,如果未能解决你的问题,请参考以下文章

删除数据后如何减小 ms access 数据库文件大小(*.accdb)(MS Office 2007)

MS Access 需要遍历 10k csv 文件,但 MS Access 数据库填满过快

拆分 MS Access 数据库需要很长时间才能打开 - 后端不断锁定和解锁

MS Access 中的 .Net 用户控件

为啥我应该关心压缩 MS Access .mdb 文件?

ms access 2003中如何改变输入框的大小