43

两种方法都返回查询返回项的列表,我在这里遗漏了什么,或者它们确实有相同的用法吗?

性能方面有什么不同吗?

4

5 回答 5

77

如果您使用默认游标 a MySQLdb.cursors.Cursor则整个结果集将在完成时存储在客户端(即 Python 列表中)cursor.execute()

因此,即使您使用

for row in cursor:

您不会减少内存占用。整个结果集已经存储在一个列表中(参见self._rowsMySQLdb/cursors.py)。

但是,如果您使用 SSCursor 或 SSDictCursor:

import MySQLdb
import MySQLdb.cursors as cursors

conn = MySQLdb.connect(..., cursorclass=cursors.SSCursor)

然后将结果集存储在服务器mysqld 中。现在你可以写

cursor = conn.cursor()
cursor.execute('SELECT * FROM HUGETABLE')
for row in cursor:
    print(row)

并且这些行将从服务器中一个接一个地获取,因此不需要 Python 首先构建一个巨大的元组列表,从而节省内存。

否则,正如其他人已经说过的那样,cursor.fetchall()并且list(cursor)本质上是相同的。

于 2013-07-25T15:08:48.003 回答
14

cursor.fetchall()并且list(cursor)本质上是一样的。不同的选项是不检索列表,而只是遍历裸游标对象:

for result in cursor:

如果结果集很大,这可能会更有效,因为它不必获取整个结果集并将其全部保存在内存中;它可以逐步获取每个项目(或以较小的批次进行批量处理)。

于 2013-07-25T14:41:34.033 回答
6

list(cursor)有效,因为游标是可迭代的;您也可以cursor在循环中使用:

for row in cursor:
    # ...

一个好的数据库适配器实现将从服务器批量获取行,节省所需的内存占用,因为它不需要在内存中保存完整的结果集。cursor.fetchall() 必须返回完整列表。

使用list(cursor)over没有什么意义cursor.fetchall();最终效果确实是一样的,但是您浪费了一个流式传输结果的机会。

于 2013-07-25T14:41:26.503 回答
5

使用 a 时值得注意的一个(MySQLdb/PyMySQL 特有的)区别DictCursor是它list(cursor)总是给你一个列表,而cursor.fetchall()给你一个列表,除非结果集为空,在这种情况下它给你一个空元组。在 MySQLdb 中就是这种情况,在较新的PyMySQL中仍然是这种情况,由于向后兼容的原因,它不会被修复。虽然这并不违反 Python 数据库 API 规范,但它仍然令人惊讶,并且很容易导致由于错误地假设结果是一个列表而导致的类型错误,而不仅仅是一个序列

鉴于上述情况,我建议始终支持,以避免list(cursor)cursor.fetchall()结果集为空的边缘情况下被神秘的类型错误所吸引。

于 2016-10-23T12:25:56.633 回答
-1

您可以使用列表推导将元组中的项目放入列表中:

conn = mysql.connector.connect()
cursor = conn.cursor()
sql = "SELECT column_name FROM db.table_name;"
cursor.execute(sql)

results = cursor.fetchall()
# bring the first item of the tuple in your results here
item_0_in_result = [_[0] for _ in results]

于 2019-10-15T12:18:39.213 回答