MS-Access数据库在插入时变得非常大
我有一个数据库,需要通过一些Python脚本定期导入大量数据。压缩后,一个月的数据大约是280MB,但在导入过程中,文件大小会膨胀到超过1GB。
考虑到mdb文件的大小限制是2GB,这让我有点担心。除了把插入操作分成小块,并在每次插入后进行压缩,还有没有其他方法可以避免文件大小的增加呢?
需要注意的是,在这个过程中没有创建或删除临时表,只是在现有表中插入数据。
为了避免大家的评论:是的,我必须把这些数据存储在Access 2003中。不,我不能升级到Access 2007。
如果有帮助的话,我可以先在sqlite中处理数据。
编辑:
再补充一些信息(有些已经在我的评论中提到过):
- 数据是在Python中逐个表生成的,然后通过odbc批量插入该表的所有记录。
- 所有处理都在Python中进行,mdb文件只是用来存储数据。
- 所有插入的字段都是有效的字段(没有因为唯一键冲突等原因被排除)。
基于以上信息,我会研究如何通过odbc禁用行级锁定,并考虑对数据进行预排序和/或移除再重新建立索引。感谢大家的建议。
欢迎任何进一步的建议。
6 个回答
一个常见的技巧,如果在应用的结构和语义上可行,就是使用多个带有链接表的MDB文件。
此外,插入数据的方式也很重要,这会影响文件大小的增长速度……比如:批量插入和一次插入一条或几条记录,按照特定索引进行排序,索引的数量(就像你提到的,在插入阶段可以考虑暂时去掉一些索引)……
可以尝试一种预处理的方法,比如把新记录存储到一个单独的链接表中,采用堆的方式(没有索引),然后再对这些数据进行排序和索引,最后“批量加载”到真正的目标位置。在SQLite中进行类似的预处理(在问题中有提到)也能达到同样的效果。保持“全部使用MDB”可能更简单(需要学习的语言/流程更少,互操作性问题也少[希望如此;-)]……)
编辑:关于为什么以排序/批量的方式插入记录可能会减缓MDB文件的增长速度(这是Tony Toews的问题)
MDB文件增长速度快于添加文本/数据的速度的原因之一是,当信息被添加时,一些构成索引的节点需要重新排列(比如溢出/重新平衡等)。这种节点管理的方式似乎是为了速度而不是磁盘空间和整洁性而设计的,这种方法通常对简单的应用和小数据量非常有效。我不清楚具体的管理逻辑,但我怀疑在很多情况下,节点操作会导致某个节点(或大部分节点)被重新复制,而旧的位置只是被标记为空闲/未使用,但并没有被删除/压缩/重用。我确实有一些“临床”的(虽然有点过时)证据表明,通过批量插入,我们实际上限制了这种重复发生的机会,从而减缓了文件的增长。
再次编辑:在阅读和讨论Tony Toews和Albert Kallal的内容后,似乎Jet Engine 4.0中更显著的膨胀来源是锁定的实现方式。因此,设置数据库为单用户模式以避免这个问题是很重要的。(想了解更多细节,请阅读Tony和Albert的回复。)
有一点需要注意的是,在追加查询中可能会出现一些记录,但由于重复的键值、必填字段为空等原因,这些记录并没有被插入到数据中。虽然这些记录没有被插入,Access 还是会为它们分配空间。
我知道的唯一重要的事情是,确保你对数据库文件有独占的访问权限。如果在白天进行操作,这可能会很难实现。我注意到,从 Jet 3.51(在 Access 97 中使用)到 Jet 4.0(在 Access 2000 中使用)时,Access 的 MDB 文件在进行记录追加时变得越来越大。我觉得如果 MDB 文件被多人使用,那么记录的插入是按每 4k 页进行的,而不是尽可能多地填充到一页中。这可能是因为这样可以加快索引的插入和更新操作。
现在,压缩确实会尽可能把更多的记录放在同一个 4k 页中,但这对你并没有帮助。
你确定行锁定功能是关闭的吗?在我的情况下,关闭行锁定后,处理一个5兆的文件时,文件大小减少了超过100兆。换句话说,关闭行锁定后,文件几乎没有增长,最终大小大约是6兆。而如果开启行锁定,进行同样的操作,文件大小会超过100兆。
行锁定在处理记录集时是导致文件膨胀的一个大问题,因为它会把每条记录填充到一个页面的大小。
你这里有安装ms-access吗,还是仅仅在用JET(JET是ms-access使用的数据引擎,你可以不安装access也使用JET)。
在ms-access中打开数据库,然后去:
工具 -> 选项 在高级选项卡中,取消勾选这个框: [ ] 使用记录级锁定打开数据库。
这样不仅会大大减少文件的膨胀,还会让速度提高十倍。
这里还有一个注册表设置可以使用。
另外,你是用odbc连接,还是oleDB连接?
你可以尝试:
Set rs = New ADODB.Recordset With rs .ActiveConnection = RsCnn .Properties("Jet OLEDB:Locking Granularity") = 1
尝试从access中更改这个设置,退出后再重新进入,然后进行压缩和修复。接着运行你的测试导入……膨胀的问题应该就会消失。
其实没有必要使用行锁定来打开数据库。如果你关闭这个功能,文件大小的膨胀就可以降到最低。
想要进一步了解和查看示例,可以看看这里: ACEDAO支持行级锁定吗?