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

如何在Python sqlite3中将现有的db文件加载到内存中?,python,performance,sqlite,Python,Performance,Sqlite,我有一个现有的sqlite3db文件,需要对其进行一些广泛的计算。从该文件执行计算的速度非常慢,而且由于该文件不大~10 MB,因此将其加载到内存中应该没有问题 是否有Pythonic方法将现有文件加载到内存中以加快计算速度?sqlite支持内存数据库 在python中,您将使用:memory:数据库名称 也许您可以打开两个数据库,一个来自文件,一个位于内存中的空数据库,将文件数据库中的所有内容迁移到内存中,然后进一步使用内存数据库进行计算。[r]eturns迭代器以SQL文本格式转储数据库。在

我有一个现有的sqlite3db文件,需要对其进行一些广泛的计算。从该文件执行计算的速度非常慢,而且由于该文件不大~10 MB,因此将其加载到内存中应该没有问题


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

sqlite支持内存数据库

在python中,您将使用:memory:数据库名称

也许您可以打开两个数据库,一个来自文件,一个位于内存中的空数据库,将文件数据库中的所有内容迁移到内存中,然后进一步使用内存数据库进行计算。

[r]eturns迭代器以SQL文本格式转储数据库。在保存内存中数据库以便以后恢复时非常有用。此函数提供与sqlite3 shell中的.dump命令相同的功能


获得这样一个迭代器,将基于磁盘的数据库转储到基于内存的数据库中,就可以开始计算了。计算完成后,只需通过另一种方式将数据转储回磁盘。

首先,您应该尝试找出导致您所观察到的速度缓慢的原因。你在给桌子写信吗?写操作是否足够大,这样就不会将不必要的临时结果保存到磁盘?是否可以更改写入以转到临时表?你能忍受吗

我不认为这个功能在Python模块中公开,但是sqlite有一个听起来正是您所要求的:一种从一个数据库复制到另一个数据库的方法,其中任何一个都可能是内存中的数据库,它几乎可以自动工作,而不需要任何用户可见的表枚举。也许会暴露这一点


另一种选择是,如果您对环境有足够的控制权,则创建一个ram磁盘,并将文件复制到该磁盘。

这一点以前已经得到了回答,包括

您没有提到操作系统,但WindowsXP的一个窍门是,不管您有多少内存,它默认为10MB的文件缓存。在系统配备64MB等设备的年代,这一点很有意义。此消息有几个链接:


以下是我为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

下面是一种将SQLite db读入内存的相对简单的方法。根据您在操作数据方面的偏好,您可以使用Pandas dataframe,也可以将表写入内存中的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和内存速度。

怎么样?即使其他客户端或同时通过同一连接访问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总是有一个内存错误。只有使用thinwybk提到的sqlite3的备份功能,我才能加载和保存更大的SQLite数据库。您也可以用3行代码来完成同样的操作,两种方式都可以。

和的答案都非常好

当您有多个到:memory:sqlite数据库的连接时,例如在将SQLAlchemy与source.backupdest函数一起使用时,您可能最终无法将备份放入正确的内存数据库中

可以使用适当的连接字符串修复此问题:
而且不涉及任何黑客攻击,也不使用未记录的功能。

有没有快速传输数据库的方法?移动每个表并不优雅。这个答案基本上只是重复了这个问题。这很好,但是如何将转储恢复到内存数据库中?连接到基于文件的数据库,然后反过来转储。这并不漂亮,但如果你的计算真的很昂贵,它会有回报的。谢谢你深刻的回答。我只是在阅读,所以一个简单的复制到内存的技巧就可以了。这是一个非常好的建议。在Windows上运行时,我将性能除以3倍。另外,它隐式支持VFS表,我使用R*Tree和FTS,不需要任何额外的复制或备份操作。请注意,您不需要C来启用此功能,只需使用类似PRAGMA mmap_size=268435456的命令,因此它适用于支持SQLite的任何语言。我使用C。对于Python 3:从io导入Stringiot,如果您有Python 3.7+,这似乎是最好的方法。@roskakori我也这么认为;