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