Python db-api: fetchone与fetchmany和fetchall的比较
今天我和一些同事讨论了Python的数据库API中的fetchone、fetchmany和fetchall这几个方法。
我知道这几个方法的使用情况可能会根据我使用的数据库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
3 个回答
这些是特定于实现的内容。
- fetchall
这个方法会从表中获取所有的结果。当表的数据量比较小的时候,这个方法效果很好。如果表的数据量很大,fetchall可能会出问题。
它会占用大部分内存。
如果在网络上执行查询,可能会引发一些问题。
- fetchmany
fetchmany只会获取所需数量的结果。你可以逐个处理这些结果。下面是fetchmany的简单实现示例。
while True:
results = cursor.fetchmany(arraysize)
if not results:
break
for result in results:
yield result
fetchone()
这个方法用来获取查询结果中的下一行数据,返回一个单独的元组。如果没有更多数据可用,就返回None:
>>> cur.execute("SELECT * FROM test WHERE id = %s", (3,))
>>> cur.fetchone()
(3, 42, 'bar')
如果之前的execute*()调用没有产生任何结果,或者还没有进行任何调用,就会抛出一个编程错误。
fetchmany([size=cursor.arraysize])
这个方法用来获取查询结果中的下一组行,返回一个元组的列表。如果没有更多行可用,就返回一个空列表。
每次调用时要获取的行数由参数指定。如果没有给出这个参数,就会使用游标的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*()调用没有产生任何结果,或者还没有进行任何调用,就会抛出一个编程错误。
需要注意的是,size参数会影响性能。为了获得最佳性能,通常最好使用arraysize属性。如果使用了size参数,最好在每次调用fetchmany()时保持这个值不变。
列表项
fetchall()
这个方法用来获取查询结果中的所有剩余行,返回一个元组的列表。如果没有更多记录可获取,就返回一个空列表。
>>> cur.execute("SELECT * FROM test;")
>>> cur.fetchall()
[(1, 100, "abc'def"), (2, None, 'dada'), (3, 42, 'bar')]
如果之前的execute*()调用没有产生任何结果,或者还没有进行任何调用,就会抛出一个编程错误。
我觉得这确实要看具体的实现,不过你可以通过查看MySQLdb的源代码来了解它们之间的区别。根据不同的选项,mysqldb的fetch*方法会把当前的一组数据保存在内存中或者保存在服务器上,所以fetchmany和fetchone在这里有一些灵活性,可以决定哪些数据保存在(Python的)内存里,哪些保存在数据库服务器上。
PEP 249没有提供太多细节,所以我猜这是为了根据不同的数据库来优化性能,而具体的语义是由实现来决定的。