Python3 - 有没有办法在一个非常大的SQlite表上逐行迭代而不将整个表加载到本地内存中?

Mar*_*yck 19 python sqlite

我有一个非常大的表,有250,000多行,其中很多都在其中一列中包含一个大的文本块.目前它的容量为2.7GB,预计至少增长十倍.我需要在表的每一行上执行特定于python的操作,但是一次只需要访问一行.

现在我的代码看起来像这样:

c.execute('SELECT * FROM big_table') 
table = c.fetchall()
for row in table:
    do_stuff_with_row
Run Code Online (Sandbox Code Playgroud)

当表格较小时,这种工作正常,但是当我尝试运行它时,表格现在比我可用的ram和python挂起的要大.是否有更好的(更有效率的)方法在整个表上逐行迭代?

Mar*_*ers 37

cursor.fetchall() 首先将所有结果提取到列表中.

相反,您可以迭代光标本身:

c.execute('SELECT * FROM big_table') 
for row in c:
    # do_stuff_with_row
Run Code Online (Sandbox Code Playgroud)

这会根据需要生成行,而不是首先加载所有行.

  • @MarlonDyck 是的,您会为这些更新使用单独的光标。这就是为什么数据库驱动程序有游标的概念:-) (6认同)
  • 这种方法非常适合我的要求,但限制我在迭代时编辑表格。对每一行执行操作后,我无法再像以前一样使用 c.execute('UPDATE table WHERE x = y') 更新它们。我目前正在使用第二个光标对象来处理更新。这是执行此操作的正确方法吗?请记住,我正在执行的操作在 SQL 中是不可能的。 (2认同)
  • @PirateApp:取决于,预期结果是什么?所有行和列的矩阵?然后使用np.array(c.fetchall())一步将所有行传递给构造函数。 (2认同)
  • @PirateApp:问题是您正在将一百万行从数据库加载到numpy数组中。你为什么要这么做? (2认同)
  • @PirateApp一个SQL数据库仍然可以使用窗口和CTE(`OVER(...)`和`WITH ...`)完成这些操作 (2认同)