MS-Access数据库在插入期间变得非常大

时间:2009-10-30 16:21:54

标签: python ms-access

我有一个数据库,我经常需要通过一些python脚本导入大量数据。压缩后,单个月导入的数据大约需要280mb,但在导入文件大小时会膨胀到超过一个GB。

鉴于mdb文件的大小限制为2GB,这是一个值得关注的问题。除了将插件拆分成块并在每个插件之间压缩之外,还有什么技术可以避免文件大小的增加吗?

请注意,在此过程中不会创建/删除临时表:只需插入现有表。

并提出不可避免的评论:是的,我需要将这些数据存储在Access 2003中。不,我无法升级到Access 2007。

如果它有用,我可以在sqlite中进行预处理。

编辑:

只是添加一些更多信息(我的评论中已经列出了一些信息):

  • 数据是在逐个表的基础上用Python生成的,然后通过odbc
  • 插入该表批量的所有记录
  • 所有处理都在Python中进行:所有mdb文件正在进行存储数据
  • 所有要插入的字段都是有效字段(由于唯一的密钥违规等原因,所有字段都被排除在外)。

鉴于上述情况,我将研究如何通过odbc禁用行级锁定,并考虑预先分配数据和/或删除然后恢复索引。感谢您的建议。

任何进一步的建议仍然受到欢迎。

6 个答案:

答案 0 :(得分:4)

您确定关闭了行锁定吗?在我的情况下,当处理5兆字节文件时,关闭行锁定减少了超过100兆的膨胀。 (换句话说,在关闭行锁定到大约6兆之后文件大麦增长)。在行锁定的情况下,相同的操作会导致文件大小超过100兆。

在记录集操作期间,行锁定是一个巨大的膨胀源,因为它会将每个记录填充到页面大小。

您是否在此处安装了ms-access,或者您只是使用JET(JET是ms-access使用的数据引擎。您可以在不访问的情况下使用JET。)

以ms-access打开数据库并转到:

工具 - >选项 在高级选项卡上,取消选中该框: []使用记录级锁定打开数据库。

这不仅会在文件增长(膨胀)方面产生巨大差异,还会使速度提高10倍。

还有一个可以在这里使用的注册表设置。

而且,您使用的是odbc还是oleDB连接?

您可以尝试:

设置rs =新ADODB.Recordset 随着rs .ActiveConnection = RsCnn .Properties(“Jet OLEDB:Locking Granularity”)= 1

尝试访问设置(更改设置),退出,重新输入,然后压缩和修复。然后运行测试导入......膨胀问题应该消失。

可能不需要使用行锁定来打开数据库。如果您关闭该功能,那么您应该能够将文件大小的膨胀降低到最低限度。

对于更精细的阅读和示例,请参见此处: Does ACEDAO support row level locking?

答案 1 :(得分:3)

如果可行的话,关于应用程序的模式和语义,一个常见的技巧是使用链接表 多个MDB文件。

此外,关于文件大小的方式,插入的方式重要 ...例如:批处理,一次一个/几个记录,排序(相对于特定索引(es)),索引数量(如你所提到的那样,在插入阶段很容易丢弃一些)......

暂时是一种预处理方法,比如说将新行存储到单独的链表,堆方式(没有索引),然后对这些数据进行排序/索引是一种最小的方式,并且“批量加载” “它到了真正的目的地。 SQLite中的类似预处理(暗示有问题)将用于服务目的。保持“所有MDB”可能更容易(更少的语言/流程学习,更少的操作间问题[hopefuly; - ]] ...)

编辑:关于为什么以排序/批量方式插入记录可能会减慢MDB文件的增长速度(来自Tony Toews的问题)
MDB文件比文本/数据添加到它们的速度更快的增长倾向的原因之一(以及它们易于压缩的对应能力)是,随着信息的添加,构成该文件的一些节点必须重新安排索引(用于溢出/重新平衡等)。节点的这种管理似乎以有利于磁盘空间和协调的速度的方式实现,并且这种方法通常很好地服务于简单的应用程序/小数据。我不知道用于此类管理的具体逻辑,但我怀疑在某些情况下,节点操作会导致特定节点(或大部分节点)被重新复制,而旧位置只是标记为空闲/未使用但不是删除/压实/重用。我确实有“临床”(如果只是有点过时)的证据表明,通过批量执行插入,我们基本上限制了这种重复发生的机会,因此我们减缓了增长。

再次编辑:在阅读并讨论Tony Toews和Albert Kallal的事情之后,似乎可能更重要的膨胀来源,特别是在Jet Engine 4.0中,锁定的方式是实施即可。因此,在单用户模式下设置数据库以避免这种情况非常重要。 (阅读Tony和Albert的回复了解更多细节。

答案 2 :(得分:3)

要注意的一件事是附加查询中存在的记录,但由于重复的键值,空的必填字段等而未插入到数据中的记录。访问将分配记录所占用的空间插入。

关于我唯一重要的事情是确保您拥有对数据库文件的独占访问权限。如果在白天这样做可能是不可能的。我注意到当执行记录追加时,Access MDB开始变得更大时,Jet 3.51(在Access 97中使用)到Jet 4.0(在Access 2000中使用)的行为发生了变化。我认为如果MDB被多个人使用,则每4k页面插入一次记录,而不是填入页面中的记录数量。可能因为这使得索引插入/更新操作更快。

现在压缩确实在同一个4k页面中放置了尽可能多的记录,但这对你没有帮助。

答案 3 :(得分:1)

您的脚本是否每行数据执行一个INSERT语句?如果是这样,将数据预处理成许多行的文本文件,然后可以使用单个INSERT语句插入,这可以提高效率并减少导致其膨胀的累积临时crud。

您还可以确保在没有事务的情况下执行INSERT。是否隐式发生这取决于Jet版本和您用来完成任务的数据接口库。通过明确确定它已关闭,您可以改善这种情况。

另一种可能性是在插入之前删除索引,压缩,运行插入,压缩,重新启动索引,并运行最终的压缩。

答案 4 :(得分:0)

我发现我能够从Access链接到Sqlite并运行make table查询来导入数据。我使用了这个ODBC驱动程序:http://www.ch-werner.de/sqliteodbc/并创建了用户DNS。

答案 5 :(得分:-1)

档案 - >选项 - >当前数据库 - >检查以下选项 *使用与Microsoft Access 2010及更高版本兼容的缓存格式    *关闭时清除缓存

然后,您将通过压缩到原始大小来保存文件。