python在sqlite3db内存中插入大型元素

2024-09-28 18:56:49 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在用python进行数值模拟,得到相当大的数据对象(大约200mb)。我把它们写进sqlite3db。在将分辨率(以及数据大小)提高了大约20%之后,我在试图插入数据库时遇到内存错误。在以前的小分辨率下工作得很好。下面是一个代码片段:

def write_to_db(self, filename, dataObject, name) :
    connection  = sqlite.connect(filename)
    cursor      = connection.cursor()
    cursor.execute("CREATE TABLE pulses (ID INTEGER PRIMARY KEY, name STRING, data BLOB)")
    cursor.execute("INSERT INTO pulses(name, data) VALUES (?, ?)", (dataObjectName, sqlite.Binary(pickle.dumps(dataObject))))
    connection.commit()
    connection.close()

我在winXP下工作,1GB内存,3GB交换(没有收到windows通知,交换需要扩展),python2.6。在

提前谢谢你的帮助。 蒂姆


Tags: 数据对象内存nameexecutesqlitedata分辨率
2条回答

您在评论中询问了可能的替代存储机制。如果您存储的数据是可用RAM的五分之一,那么我认为您需要非常小心地管理内存,因为在RAM用完之前,您无法复制太多数据;而且无论如何,您都会降低性能。您可以让sqlite使用blob为您做正确的事情,因为这些blob可能很大。在

看起来您将sqlite用作一个简单的键/值存储。你考虑过使用平面文件吗?如果您需要原子性,您仍然可以使用sqlite数据库来定义平面文件存储中哪些文件是有效的。您可以安全地做到这一点:只有在干净地写入所有平面文件之后才提交到数据库,并且只有在提交数据库中的相应删除之后才能删除平面文件。在

为了实现这一点,您需要一些机制将您的dataObject序列化为Python中的文件类型对象。如果向Pickle传递一个文件类型的对象,Pickle可以为您完成这项工作,但我怀疑它仍然效率低下。在

你说你在做数值模拟;你知道纽比吗?numpy数组支持一个tofile函数,它将比pickle更有效,并且如果您还没有使用它,您可能会在模拟中获得显著的性能提升。在

注意XP只会以较小的增量增加交换。如果您的程序突然尝试使用更多的内存,并且没有足够的交换空间,那么您将得到内存错误。在

SQLite可以很好地处理大小达1GB的blob,您通常可以使用2GB。但是,在32位进程中,地址空间将用尽。在

对于较大的项目,通常建议您将大数据存储在文件中,然后将文件名存储在数据库中,但这对您来说需要做更多的工作。在

您可以通过执行以下操作来解决当前的问题:

  • 切换到使用64位。微软以150美元(市价130美元)出售一款Windows7家庭软件包,其中包括3个XP/Vista实例的升级,这样你就可以升级几台机器了。你可以用这种方法从32位XP切换到64位win7。即使不更改RAM等的数量,这样做也会立即解决问题。

  • 向pickle调用添加-1,该调用告诉它使用最新的pickle协议,该协议使用二进制而不是ascii默认编码。因此,您将获得较少的数据。有关协议版本以及哪些Python版本支持它们,请阅读文档。

  • 同时压缩pickled数据-例如bz2.compress(泡菜、垃圾(目标,-1)

这里出现问题的最可能原因是地址空间不足。一个32位的进程通常只能同时处理2GB的数据,而各种可执行文件和共享库、每个线程的堆栈、SQLite缓存等也会从该空间中减去。您将需要仔细注意您拥有的所有不同的数据项,以及它们何时处于活动状态。打电话给德尔和gc.收集()当您主动完成这些操作时,将有助于减少正在使用的并发数据量。在

相关问题 更多 >