这两种方法都返回查询返回项的列表,我有没有漏掉什么,或者它们确实具有相同的用法?
在性能方面是否有任何差异?
这两种方法都返回查询返回项的列表,我有没有漏掉什么,或者它们确实具有相同的用法?
在性能方面是否有任何差异?
MySQLdb.cursors.Cursor
,整个结果集将在客户端(即Python列表中)被存储,直到cursor.execute()
完成。for row in cursor:
您不会获得任何内存占用的减少。整个结果集已经存储在列表中(请参见MySQLdb / cursors.py中的self._rows
)。
但是,如果您使用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)
本质上是相同的。
cursor.fetchall()
和list(cursor)
本质上是相同的。不同之处在于不检索列表,而是直接循环遍历裸游标对象:
for result in cursor:
如果结果集很大,这种方法可以更加高效,因为它不需要获取整个结果集并将其全部保存在内存中;它只需逐个地(或按较小批次分批)逐步获取每个项目。
list(cursor)
可以工作是因为游标是可迭代的。你也可以在循环中使用 cursor
:
for row in cursor:
# ...
cursor.fetchall()
必须返回完整的列表。list(cursor)
而非cursor.fetchall()
几乎毫无意义;虽然最终效果相同,但却浪费了流式传输结果的机会。DictCursor
时,(针对MySQLdb/PyMySQL)需要注意的一个区别是:list(cursor)
始终会返回一个列表,而cursor.fetchall()
则只有在结果集不为空的情况下才会返回一个列表,否则它会返回一个空元组。这在MySQLdb中是这样,在新的PyMySQL中仍然如此,并且由于向后兼容性的原因不会被修复。虽然这并不违反Python数据库API规范,但仍然很令人惊讶,很容易因错误地假设结果是一个列表而导致类型错误。
基于上述原因,我建议始终优先使用list(cursor)
而不是cursor.fetchall()
,以避免在结果集为空的边缘情况下被神秘的类型错误所困扰。
您可以使用列表推导式将元组中的项转换为列表:
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]
_
作为名称是用于表示未使用的名称的约定。在这里,您正在使用它来访问一个元素,这会造成困惑。 - BlackJack
list(cursor)
可以被认为比cursor.fetchall()
更好(因为后者返回的类型不一致,有时是列表有时是元组,而前者始终返回一个列表),大多数游标实现在您开始迭代它们时会将整个结果集读入内存中。 - Mark Amery