如何在 Python sqlite3中将现有的 db 文件加载到内存中?

我有一个现有的 sqlite3数据库文件,我需要对其进行一些广泛的计算。从文件进行计算非常缓慢,而且由于文件不大(~ 10 MB) ,所以将其加载到内存中应该没有问题。

是否有一种 Python 方法将现有文件加载到内存中以加快计算速度?

49530 次浏览

Sqlite 支持内存数据库。

在 python 中,可以使用 校对: 死记硬背:数据库名称。

也许你可以打开两个数据库(一个在文件中,一个在内存中) ,把所有东西从文件数据库迁移到内存中,然后再用内存数据库进行计算。

首先,你应该试着找出是什么导致了你所观察到的缓慢。你在给桌子写信吗?在 交易内写入的内容是否足够大,以便不会将不必要的临时结果保存到磁盘?可以将写操作更改为转到临时表(使用 pragma temp_store=memory)吗?你能接受 pragma synchronous=off吗?

我不认为这个功能是在 Python 模块中公开的,但 sqlite 有一个 备份 API,听起来就像你要求的那样: 一种从一个数据库复制到另一个数据库(其中任何一个都可能是一个内存数据库)的方法,几乎可以自动工作,而不需要任何用户可见的表枚举。(也许 APSW暴露了这一点?)

另一种选择是创建一个内存磁盘(如果您对环境有足够的控制)并在那里复制文件。

这个问题以前已经得到回答,包括 在 python 中,如何在连接到 sqlite db 之前将其完全加载到内存中?的代码示例

你没有提到操作系统,但是 WindowsXP 的一个问题是,无论你有多少内存,它都默认使用10MB 的文件缓存。(这在系统配置为64MB 等的时候是有意义的)。这条信息有几个链接:

Http://marc.info/?l=sqlite-users&m=116743785223905&w=2

下面是我为烧瓶应用程序编写的代码片段:

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

以下是将 SQLitedb 读入内存的一种相对简单的方法。根据您对操作数据的偏好,您可以使用熊猫数据框,也可以将表写入内存中的 sqlite3数据库。类似地,在处理数据之后,使用相同的 df.to _ sqlite 方法将结果存储回 db 表中。

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')

如果我们必须使用一个 Python 包装器,那么没有更好的解决方案比两个通过,读和写的解决方案。 但是从3.7.17版本开始,SQLite 可以选择直接使用内存映射的 I/O 访问磁盘内容

如果要使用 mmap,则必须使用 C 接口,因为没有包装器提供它。

还有另一种硬件解决方案,内存磁盘。那么你有方便的文件 IO 和内存的速度。

sqlite3.Connection.backup(...)呢?“此方法对 SQLite 数据库进行备份,即使其他客户端正在访问该数据库,或者同一连接正在并发访问该数据库。”可用性: SQLite 3.6.11或更高版本。3.7版本新增。

import sqlite3


source = sqlite3.connect('existing_db.db')
dest = sqlite3.connect(':memory:')
source.backup(dest)

对于 Cenk Alti 的解决方案,当进程达到500MB 时,Python 3.7总是有一个 MemoryError。只有通过使用 sqlite3的备份功能(thinwypk 提到过) ,我才能够加载和保存更大的 SQLite 数据库。你也可以用3行代码做同样的事情,两种方式都可以。

@ thinwubk低吟歌手的答案都很好。

当您有多个到 :memory: sqlite 数据库的连接时,例如当与 source.backup(dest)函数一起使用 SQLAlchemy 时,您可能最终没有将备份放入“正确的”内存数据库中。

这可以通过适当的连接字符串来修复: < a href = “ https://stackoverflow. com/a/65429612/1617295”> https://stackoverflow.com/a/65429612/1617295 并不涉及任何黑客不使用未记录的功能。