указатель.fetchall () vs list (курсор) в Python

оба метода возвращают список возвращенных деталей запроса, я что-то пропустила?
или у них действительно одинаковые обычаи?
любой производительности-мудрый различия?

4 ответов


если вы используете курсор по умолчанию, а MySQLdb.cursors.Cursor, весь результирующий набор будет храниться на стороне клиента (т. е. в списке Python) к моменту cursor.execute() завершено.

поэтому, даже если вы используете

for row in cursor:

вы не получите никакого сокращения объема памяти. Весь результирующий набор уже сохранен в списке (см. self._rows in 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:

Это может быть более эффективным, если результирующий набор Большой, так как он не должен извлекать весь результирующий набор и хранить его в памяти; он может просто постепенно получить каждый элемент (или пакетировать их в меньших партиях).


a (MySQLdb/pymysql-specific) разница стоит отметить при использовании DictCursor Это list(cursor) всегда будет давать вам список, в то время как cursor.fetchall() дает вам список если результирующий набор пуст, в этом случае он дает вам пустой кортеж. Это было так в MySQLdb и остается таковым в более новом PyMySQL, где он не будет исправлено для обратной совместимости. Пока это не является нарушением API базы данных Python Спецификация, это все еще удивительно и может легко привести к ошибке типа, вызванной неправильным предположением, что результатом является список, а не последовательность.

учитывая вышесказанное, я предлагаю всегда благосклонно list(cursor) над cursor.fetchall(), чтобы избежать когда-либо попасться на загадочную ошибку типа в крайнем случае, когда ваш результирующий набор пуст.


list(cursor) работает, потому что курсор-это итерируемый; вы также можете использовать cursor в цикле:

for row in cursor:
    # ...

хорошая реализация адаптера базы данных будет получать строки партиями с сервера, экономя на требуемом объеме памяти, поскольку ему не нужно будет удерживать полное результирующий набор, в памяти. cursor.fetchall() и вместо того, чтобы вернуть полный список.

мало смысла в использовании list(cursor) над cursor.fetchall(); конечным результатом является то же, но вместо этого вы упустили возможность транслировать результаты.