Python3 -有没有一种方法可以在一个非常大的SQlite表上逐行搜索,而不需要将整个表加载到本地内存中?

n1bvdmb6  于 12个月前  发布在  SQLite
关注(0)|答案(2)|浏览(208)

我有一个非常大的表,有250,000多行,其中许多列包含一个大的文本块。现在它是2.7GB,预计将增长至少十倍。我需要对表的每一行执行Python特定的操作,但每次只需要访问一行。
现在我的代码看起来像这样:

c.execute('SELECT * FROM big_table') 
table = c.fetchall()
for row in table:
    do_stuff_with_row

字符串
当表较小时,这工作得很好,但是现在表大于我可用的ram,当我尝试运行它时,python挂起。有没有更好的(更有效的ram)方法在整个表中逐行搜索?

3bygqnnd

3bygqnnd1#

cursor.fetchall()首先将所有结果提取到列表中。
相反,您可以在光标 * 本身 * 上单击鼠标:

c.execute('SELECT * FROM big_table') 
for row in c:
    # do_stuff_with_row

字符串
这会根据需要生成行,而不是先将它们全部加载。

ahy6op9u

ahy6op9u2#

为了提供一个测试what was mentioned by Martijn的最小可运行示例,创建一个具有10m个点的数据库:

f="10m.sqlite"
rm -f "$f"
sqlite3 "$f" 'create table t(x integer)'
time sqlite3 "$f" 'insert into t select value as x from generate_series(1,10000000)'

字符串
使用此程序循环访问数据库:
main.py

#!/usr/bin/env python
import sqlite3
con = sqlite3.connect("10m.sqlite")
cur = con.cursor()
cur.execute('select * from t')
x = 0
for (i,) in cur.fetchAll():
    x += i % 2
print(x)


使用Peak memory usage of a linux/unix process获得最大内存使用量

command time -v ./main.py |& grep 'Maximum resident'


给出:

Maximum resident set size (kbytes): 873600


所以大约900 MB,哇。我们天真地期望每个int有8个字节,最多80 MB。然后如果我们这样做:

for (i,) in cur:


它只有11 MB:

Maximum resident set size (kbytes): 11256


在Python 3.11.4,Ubuntu 23.04上测试。

相关问题