我有一个现成的sqlite3
数据库文件,需要进行一些复杂的计算。直接从文件中进行计算速度非常慢,而且由于文件不大(~10 MB
),所以将其加载到内存中应该没有问题。
是否有一种Pythonic的方法可以将现有文件加载到内存中以加快计算速度?
我有一个现成的sqlite3
数据库文件,需要进行一些复杂的计算。直接从文件中进行计算速度非常慢,而且由于文件不大(~10 MB
),所以将其加载到内存中应该没有问题。
是否有一种Pythonic的方法可以将现有文件加载到内存中以加快计算速度?
这里是我为我的Flask应用编写的片段:
import sqlite3
from io import StringIO
def init_sqlite_db(app):
# Read database to tempfile
con = sqlite3.connect(app.config['SQLITE_DATABASE'])
tempfile = StringIO()
for line in con.iterdump():
tempfile.write('%s\n' % line)
con.close()
tempfile.seek(0)
# Create a database in memory and import from tempfile
app.sqlite = sqlite3.connect(":memory:")
app.sqlite.cursor().executescript(tempfile.read())
app.sqlite.commit()
app.sqlite.row_factory = sqlite3.Row
那么 sqlite3.Connection.backup(...)
呢?“该方法可在其他客户端或同一连接并发访问 SQLite 数据库时备份 SQLite 数据库。” 可用性:SQLite 3.6.11 或更高版本。自版本 3.7 起新增。
import sqlite3
source = sqlite3.connect('existing_db.db')
dest = sqlite3.connect(':memory:')
source.backup(dest)
sqlite3.Connection.iterdump
返回一个迭代器,可将数据库以SQL文本格式导出。在保存内存中的数据库以备将来恢复时非常有用。此函数提供了与sqlite3 shell中的.dump
命令相同的功能。
获得此类迭代器并将基于磁盘的数据库导出到基于内存的数据库,然后您就可以开始进行计算了。当计算完成后,只需反向导出回磁盘即可。
首先,您应该尝试找出导致您观察到的缓慢的原因。您是否正在写入表格?您的写入是否足够大的事务,以便不会将不必要的临时结果保存到磁盘上?您是否可以更改写入以进入临时表(使用{{link2:pragma temp_store=memory
}})?您是否可以接受{{link3:pragma synchronous=off
}}?
我不认为Python模块中公开了此功能,但sqlite有一个备份API,听起来正是您所要求的:一种从一个数据库复制到另一个数据库的方法(其中任何一个都可以是内存数据库),而且几乎自动地工作,无需用户可见枚举表格。(也许APSW公开了这个功能?)
另一个选择是创建一个ram磁盘(如果您对环境具有足够的控制权),然后将文件复制到那里。
PRAGMA mmap_size = 268435456
的命令即可,因此它适用于任何支持SQLite的语言(我使用C#)。 - Simon Mourier这里有一种相对简单的方法,可以将SQLite数据库读入内存。根据您对数据操作的偏好,您可以使用Pandas数据框架或将表格写入内存中的sqlite3数据库。类似地,在操纵数据后,您可以使用相同的df.to_sqlite方法将结果存储回数据库表中。
import sqlite3 as lite
from pandas.io.sql import read_sql
from sqlalchemy import create_engine
engine = create_engine('sqlite://')
c = engine.connect()
conmem = c.connection
con = lite.connect('ait.sqlite', isolation_level=None) #Here is the connection to <ait.sqlite> residing on disk
cur = con.cursor()
sqlx = 'SELECT * FROM Table'
df = read_sql(sqlx, con, coerce_float=True, params=None)
#Read SQLite table into a panda dataframe
df.to_sql(con=conmem, name='Table', if_exists='replace', flavor='sqlite')
这个问题已经在In python, how can I load a sqlite db completely to memory before connecting to it?中得到了解答,包括代码示例。
您没有提及操作系统,但是Windows XP的一个陷阱是它默认使用10MB的文件缓存,无论您有多少内存。(这在64MB等系统出现的时代是有意义的)。这个信息有几个链接:
使用Cenk Alti的解决方案,当进程达到500MB时,我总是在Python 3.7中遇到MemoryError问题。只有使用sqlite3的备份功能(由thinwybk提到),我才能够加载和保存更大的SQLite数据库。同样,您也可以只用三行代码实现相同的功能。
如果您同时使用SQLAlchemy和source.backup(dest)
函数连接到多个:memory:
sqlite数据库,那么您可能会发现备份没有放入“正确”的内存数据库中。
这可以通过使用适当的连接字符串来解决:https://dev59.com/Kbvoa4cB1Zd3GeqP9r-b#65429612,而且不涉及任何黑客或未记录的功能的使用。
SQLite支持内存数据库。
在Python中,您可以使用:memory:作为数据库名称。
也许您可以打开两个数据库(一个来自文件,一个空的内存数据库),将文件数据库中的所有内容迁移到内存中,然后进一步使用内存数据库进行计算。
from io import StringIO
- Emre