Оба метода возвращают список возвращенных элементов запроса, я что-то здесь упустил?
Или они действительно имеют идентичные использования?
Есть ли различия в производительности?
Cursor.fetchall() vs list (курсор) в Python
Ответ 1
Если вы используете курсор по умолчанию, MySQLdb.cursors.Cursor
, весь результирующий набор будет сохранен на стороне клиента (т.е. в списке Python) к моменту завершения cursor.execute()
.
Поэтому, даже если вы используете
for row in cursor:
у вас не будет уменьшения объема памяти. Весь набор результатов уже сохранен в списке (см. self._rows
в MySQLdb/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)
по существу совпадают.
Ответ 2
cursor.fetchall()
и list(cursor)
по существу одинаковы. Другой вариант состоит в том, чтобы не извлекать список, а вместо этого просто перебирать объект с открытым курсором:
for result in cursor:
Это может быть более эффективным, если результирующий набор является большим, так как ему не нужно извлекать весь набор результатов и хранить все в памяти; он может просто увеличивать каждый элемент (или партии их меньшими партиями).
Ответ 3
Значение A (с учетом MySQLdb/PyMySQL), которое стоит отметить при использовании DictCursor
, заключается в том, что list(cursor)
всегда будет предоставлять вам список, а cursor.fetchall()
предоставляет вам список, если результирующий набор пуст, и в этом случае это дает вам пустой кортеж. Это было в MySQLdb и остается в случае нового PyMySQL, где не будет исправлено для соображений обратной совместимости. Хотя это не является нарушением спецификации API Python Database, это все еще удивительно и может легко привести к ошибке типа, вызванной ошибочным допущением, что результат это список, а не просто последовательность.
Учитывая вышеизложенное, я предлагаю всегда одобрять list(cursor)
над cursor.fetchall()
, чтобы избежать попадания в таинственный тип ошибки в случае края, где ваш результирующий набор пуст.
Ответ 4
list(cursor)
работает, потому что курсор является итерируемым; вы также можете использовать cursor
в цикле:
for row in cursor:
# ...
Хорошая реализация адаптера базы данных будет извлекать строки в пакетах с сервера, сохраняя требуемый объем памяти, поскольку ему не нужно удерживать полный набор результатов в памяти. cursor.fetchall()
должен вернуть полный список.
Нет смысла использовать list(cursor)
над cursor.fetchall()
; конечный эффект тогда действительно тот же самый, но вы теряли возможность использовать результаты вместо этого.
Ответ 5
Вы можете использовать списки, чтобы поместить элемент из вашего кортежа в список:
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]