web-dev-qa-db-ja.com

Pythonのcursor.fetchall()vs list(cursor)

どちらのメソッドも、クエリで返されたアイテムのリストを返しますが、ここで何か見逃していませんか?
それとも、まったく同じ使い方をしていますか?
パフォーマンス上の違いはありますか?

34
NZal

デフォルトのカーソルを使用している場合、_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)
_

行はサーバーから1つずつフェッチされるため、最初にタプルの巨大なリストを作成するためにPythonを必要とせず、したがってメモリを節約できます。

それ以外の場合、他の人がすでに述べているように、cursor.fetchall()list(cursor)は本質的に同じです。

67
unutbu

cursor.fetchall()list(cursor)は本質的に同じです。別のオプションは、リストを取得せず、代わりにベアカーソルオブジェクトをループするだけです。

for result in cursor:

結果セットが大きい場合、結果セット全体をフェッチしてメモリ内にすべて保持する必要がないため、これはより効率的です。各アイテムをインクリメンタルに取得できます(または、より小さなバッチでバッチ処理できます)。

11
Amber

DictCursorを使用する場合に注意する価値のある(MySQLdb/PyMySQL固有の)違いは、list(cursor)が常にリストを提供し、cursor.fetchall()がリストを提供することですunless結果セットは空です。その場合、空のTupleが返されます。これはMySQLdbの場合であり、より新しい PyMySQL の場合のままです。ここでは 修正されません 後方互換性の理由からです。これは Python Database API Specification の違反ではありませんが、それでも驚くべきことであり、結果がlist、単なるsequenceではなく。

上記を考えると、list(cursor)よりもcursor.fetchall()を優先することをお勧めします。これにより、結果セットが空のEdgeのケースでミステリアスな型エラーに巻き込まれないようにできます。

4
Mark Amery

list(cursor)は、カーソルが反復可能であるため機能します。ループでcursorを使用することもできます。

_for row in cursor:
    # ...
_

適切なデータベースアダプター実装は、サーバーからバッチで行をフェッチし、メモリにfull結果セットを保持する必要がないため、必要なメモリフットプリントを節約します。 cursor.fetchall()has代わりに完全なリストを返します。

list(cursor) over cursor.fetchall();を使用してもほとんど意味がありません。最終的な効果は実際には同じですが、結果をストリーミングする機会を無駄にしました。

2
Martijn Pieters