【问题标题】:Is sqlite3 fetchall necessary?sqlite3 fetchall 有必要吗?
【发布时间】:2014-01-24 14:10:22
【问题描述】:

我刚开始使用 sqlite3 和 python 。 我想知道两者之间的区别:

cursor = db.execute("SELECT customer FROM table")
    for row in cursor:
              print row[0]

cursor = db.execute("SELECT customer FROM table")
    for row in cursor.fetchall():
              print row[0]

除了cursor<type 'sqlite3.Cursor'>cursor.fetchall()<type 'list'>,两者的结果是一样的。

是否存在差异、偏好或特定情况,其中一个比另一个更受欢迎?

【问题讨论】:

    标签: python sql sqlite


    【解决方案1】:

    fetchall() 将所有记录读入内存,然后返回该列表。

    当遍历游标本身时,只有在需要时才会读取行。 当您有大量数据并且可以逐行处理时,这会更有效。

    【讨论】:

    • 我认为重要的是要考虑在执行选择查询时可能会并行写入数据库。考虑如果您想更新您正在迭代的某些行,或者如果有另一个进程或线程可以进行此类更新,会发生什么。如果您遍历游标本身,您的查询可能会突然停止返回它应该具有的行,但是如果您将所有行提取到内存中,您将获得该时间窗口内的行而无需修改,无论好坏。
    • @DavidOldford SQLite 总是使用serializable transactions;这不可能发生。
    • 这取决于您是否使用事务处理您所做的一切。我还没有真正测试过多线程场景,但是在单线程应用程序中,如果您使用游标使用选择遍历要更新的行列表并尝试在此循环中更新它们,您将不会更新您期望的所有行.如果您获取所有行,则此方法将起作用。我自己没想到它可能是由序列化事务系统引起的,即在游标上迭代期间的事务改变了底层数据,而游标只是把它的胆量吐了出来。
    【解决方案2】:

    主要区别正是对fetchall() 的调用。通过发出fetchall(),它将返回一个list 对象,其中填充了初始查询中剩余的所有元素(如果您还没有得到任何元素,则为所有元素)。这有几个缺点:

    1. 增加内存使用量:通过将所有查询的元素存储在一个列表中,这可能是巨大的
    2. 性能不佳:如果元素很多,填充列表可能会很慢
    3. 进程终止:如果是巨大的查询,那么您的程序可能会因内存不足而崩溃。

    当您改为使用 cursor 迭代器 (for e in cursor:) 时,您会懒惰地获得查询的行。这意味着,只有在程序需要时才一个一个地返回。

    当然,您的两个代码 sn-ps 的输出是相同的,但在内部使用 fetchall() 与仅使用 cursor 之间存在巨大的性能缺陷。

    希望这会有所帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-03
      • 2012-12-14
      • 2012-09-12
      • 2019-09-14
      • 2021-11-11
      • 2016-04-24
      • 2011-06-06
      • 1970-01-01
      相关资源
      最近更新 更多