簡體   English   中英

python在sqlite3 db中插入大元素-內存錯誤

[英]python inserting large element in sqlite3 db - memory error

我正在用python進行數值模擬,從而導致很大的數據對象(大約200 MB)。 我將它們寫入sqlite3數據庫。 將分辨率(以及數據大小)提高約20%之后,在嘗試插入db時出現內存錯誤。 在使用較小的分辨率之前就可以正常工作。 這是一個代碼片段:

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 RAM,3GB交換下工作(並且未收到交換擴展需要擴展的Windows通知),Python 2.6。

在此先感謝您的幫助。 提姆

請注意,XP只會以較小的增量增加交換。 如果您的程序突然嘗試使用更多的內存,而交換空間不足,則會出現內存錯誤。

SQLite可以非常高興地使用不超過1GB的blob,並且通常可以使用2GB。 但是,您將在32位進程中用完地址空間。

通常建議將較大的數據存儲在文件中,然后將文件名存儲在數據庫中的較大項,但這對您來說是更多的工作。

您可以通過執行以下操作來解決當前的問題:

  • 切換到使用64位。 微軟出售的Windows 7 Family Pack包括3個XP / Vista實例的升級,價格為150美元(市場價格為130美元),因此您可以升級多台計算機。 您可以通過這種方式從32位XP切換到64位Win 7。 即使不更改RAM等的數量,僅執行此操作即可立即解決您的問題。

  • 將-1添加到pickle調用中,告訴它使用最新的pickle協議,該協議使用二進制而不是ascii默認編碼。 結果,您將獲得較少的數據。 閱讀該文檔以獲取有關協議版本以及哪些Python版本支持它們的更多信息。

  • 還壓縮腌制的數據-例如bz2.compress(pickle.dumps(obj,-1)

您出現問題的最可能原因是地址空間不足。 一個32位的進程通常只能同時處理2GB的數據,並且各種可執行文件和共享庫,每個線程的堆棧,SQLite緩存等也將從該空間中減去。 您將需要特別注意所擁有的所有各種數據項以及它們何時處於活動狀態。 主動處理完del和gc.collect()會有助於減少使用中的並發數據量。

您在評論中詢問可能的替代存儲機制。 如果要存儲的數據是可用RAM的五分之一,那么我要說,您需要非常仔細地管理內存,因為在用完RAM之前不能復制太多數據; 在任何情況下,您都將失去性能。 由於BLOB可能很大,因此您可能能夠使sqlite為您做正確的事情。

看起來您正在使用sqlite作為簡單的鍵/值存儲。 您是否考慮過使用平面文件? 如果需要ATOMicity,您仍然可以使用sqlite數據庫來定義平面文件存儲中的哪些文件有效。 您可以通過以下方式來安全地執行此操作:僅在干凈地寫入所有平面文件之后才提交給數據庫,並且僅在提交數據庫中的相應刪除后才刪除平面文件。

為了使這項工作有效,您需要某種機制將Python中的dataObject序列dataObject文件類型的對象。 如果您將它傳遞給文件類型的對象,Pickle可以為您完成此操作,但是我懷疑它仍然效率很低。

您說您在進行數值模擬; 你知道numpy嗎? numpy數組支持一個tofile函數,該函數將比酸洗更有效,如果您尚未使用它,則可能會在模擬中獲得顯着的性能提升。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM