【问题标题】:Python db-api: fetchone vs fetchmany vs fetchallPython db-api:fetchone vs fetchmany vs fetchall
【发布时间】:2011-07-08 13:56:33
【问题描述】:

我今天刚刚和一些同事讨论了 python 的 db-api fetchone vs fetchmany vs fetchall。

我确信其中每一个的用例都取决于我正在使用的 db-api 的实现,但总的来说,fetchone、fetchmany 和 fetchall 的用例是什么?

换句话说,以下是等价的吗?还是其中有一个比其他的更受欢迎?如果是,在哪些情况下?

cursor.execute("SELECT id, name FROM `table`")
for i in xrange(cursor.rowcount):
    id, name = cursor.fetchone()
    print id, name


cursor.execute("SELECT id, name FROM `table`")
result = cursor.fetchmany()
while result:
    for id, name in result:
        print id, name
    result = cursor.fetchmany()


cursor.execute("SELECT id, name FROM `table`")
for id, name in cursor.fetchall():
    print id, name

【问题讨论】:

    标签: python mysql python-db-api


    【解决方案1】:

    根据official psycopg2 documentation

    fetchone()

    获取查询结果集的下一行,返回单个元组,或者当没有更多数据可用时返回 None:

    >>> cur.execute("SELECT * FROM test WHERE id = %s", (3,))
    >>> cur.fetchone()
    
    (3, 42, 'bar')
    

    如果先前对 execute*() 的调用未产生任何结果集或尚未发出任何调用,则会引发 ProgrammingError。

    fetchmany([size=cursor.arraysize])

    获取查询结果的下一组行,返回一个元组列表。当没有更多行可用时返回一个空列表。

    每次调用获取的行数由参数指定。如果没有给出,游标的数组大小决定了要获取的行数。该方法应尝试获取 size 参数指示的尽可能多的行。如果由于指定的行数不可用而无法执行此操作,则可能会返回更少的行:

    >>> cur.execute("SELECT * FROM test;")
    >>> cur.fetchmany(2)
    [(1, 100, "abc'def"), (2, None, 'dada')]
    >>> cur.fetchmany(2)
    [(3, 42, 'bar')]
    >>> cur.fetchmany(2)
    []
    

    如果先前对 execute*() 的调用未产生任何结果集或尚未发出任何调用,则会引发 ProgrammingError。

    请注意,size 参数涉及性能注意事项。为了获得最佳性能,通常最好使用 arraysize 属性。如果使用了 size 参数,那么它最好在一次 fetchmany() 调用到下一次调用中保持相同的值。

    列表项

    fetchall()

    获取查询结果的所有(剩余)行,将它们作为元组列表返回。如果没有更多记录要获取,则返回一个空列表。

    >>> cur.execute("SELECT * FROM test;")
    >>> cur.fetchall()
    [(1, 100, "abc'def"), (2, None, 'dada'), (3, 42, 'bar')]
    

    如果先前对 execute*() 的调用未产生任何结果集或尚未发出任何调用,则会引发 ProgrammingError。

    【讨论】:

      【解决方案2】:

      这些是特定于实现的。

      • 全取

      将从表格中获取所有结果。当表的大小较小时,这将更好地工作。如果表大小更大,则 fetchall 在这些情况下将失败。

      将使用大部分内存。

      如果在网络上进行查询,可能会出现一些问题。

      • fetchmany

      fetchmany 将只获得所需数量的结果。您可以产生结果和过程。 fetchmany 实现的简单片段。

         while True:
          results = cursor.fetchmany(arraysize)
          if not results:
              break
          for result in results:
              yield result
      

      【讨论】:

      • 从 Python 3.3 开始,使用 yield from results 消除 for 循环应该会更好。
      • @ebk 来源或解释?
      • @khawabonga 检查PEP 380this answer
      【解决方案3】:

      我认为这确实取决于实现,但您可以通过查看 MySQLdb 源来了解差异。根据选项,mysqldb fetch* 将当前行集保留在内存或服务器端,因此 fetchmany 与 fetchone 在此处具有一定的灵活性,可以知道要在(python 的)内存中保留什么以及要在 db 服务器端保留什么。

      PEP 249 没有提供太多细节,所以我想这是根据数据库优化事物,而确切的语义是实现定义的。

      【讨论】:

      • 我发现这些使用的内存量存在差异,其中 fetchall() 使用的内存最多。
      • 这三个 fetch 命令也让我摸不着头脑。如果有问题的 Python 运行在与 mySQL 服务器相同的服务器上怎么办?
      • 我的困惑源于 SQL 选择查询可以有 LIMIT 的事实,因此 fetchonefetchmany 的目的是什么?事实上,如果您选择了一个没有限制的查询,您将获得整个表格。如果我仍然只使用fetchone,这是否意味着大量行无缘无故地从服务器传输到客户端?在那种情况下,你为什么要使用fetchone,而使用LIMIT 1总是更有效。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-06-22
      • 1970-01-01
      • 2019-02-28
      • 1970-01-01
      • 2017-08-07
      • 1970-01-01
      • 2019-12-19
      相关资源
      最近更新 更多