28

Python でpsycopg2モジュールを使用して postgres データベースから読み取っています。100 万行を超える列のすべての行に対して操作を行う必要があります。

cur.fetchall()障害が発生したり、サーバーがダウンしたりすることを知りたいですか? (私のRAMは、そのすべてのデータを保持するにはそれほど大きくない可能性があるため)

q="SELECT names from myTable;"
cur.execute(q)
rows=cur.fetchall()
for row in rows:
    doSomething(row)

これを行うより賢い方法は何ですか?

4

6 に答える 6

30

サーバー側カーソルの使用を検討してください:

データベース クエリが実行されると、Psycopg カーソルは通常、バックエンドから返されたすべてのレコードをフェッチし、それらをクライアント プロセスに転送します。クエリが大量のデータを返した場合、それに比例して大量のメモリがクライアントによって割り当てられます。

データセットが大きすぎてクライアント側で実際に処理できない場合は、サーバー側カーソルを作成できます。この種のカーソルを使用すると、制御された量のデータのみをクライアントに転送できるため、大きなデータセットを完全にメモリに保持することなく調べることができます。

次に例を示します。

cursor.execute("DECLARE super_cursor BINARY CURSOR FOR SELECT names FROM myTable")
while True:
    cursor.execute("FETCH 1000 FROM super_cursor")
    rows = cursor.fetchall()

    if not rows:
        break

    for row in rows:
        doSomething(row)
于 2013-07-29T20:17:39.513 に答える
27

fetchall()制限までフェッチするarraysizeため、データベースへの大規模なヒットを防ぐために、管理可能なバッチで行をフェッチするか、使い果たされるまでカーソルをステップスルーすることができます。

row = cur.fetchone()
while row:
   # do something with row
   row = cur.fetchone()
于 2013-07-29T20:20:09.727 に答える
3

これは、管理速度を備えた単純なサーバー側カーソルに使用するコードです。fetchmany

原則は、Psycopg2 で名前付きカーソルitersizeを使用し、一度に多くの行をロードするのに適した方法を提供するfetchmanyことですが、その 1 回のループでfor rec in cursor暗黙的なfetchnone().

このコードを使用すると、1 時間と 200 メガ RAM で、数十億行のテーブルから 1 億 5000 万行のクエリを実行できます。

于 2015-04-17T19:28:21.867 に答える