2017-01-03 9 views
2

でサーバー側カーソルを使用しますは、どのように私は4million行を持つテーブルがあると私はexectureするpsycopg2を使用psycopg2

SELECT * FROM ..WHERE query 

私は、サーバー側のカーソルの前に聞いたことがないと私はそのAを読んでいますあなたが多くの結果を期待するときは良い練習。

私はドキュメントが少し限られていると私はいくつかの基本的な質問があります。私のように、サーバー側のカーソルを宣言

まず:

cur = conn.cursor('cursor-name') 

その後、私のようにクエリを実行します。

cur.itersize = 10000 
sqlstr = "SELECT clmn1, clmn2 FROM public.table WHERE clmn1 LIKE 'At%'" 
cur.execute(sqlstr) 

私の質問は:私は今、何をしますか?どのように結果を得るのですか?

私のように行を反復ください:

row = cur.fetchone() 
while row: 
    row = cur.fetchone() 

または私は(fetchmanyを使用)、私はこれを実行します。

row = cur.fetchmany(10) 

しかし、どのように私は結果を「スクロール」可能な第2のケースでは?

また、itersizeのポイントは何ですか?

答えて

1

さらにcur.fetchmany(n)に、あなたは、PostgreSQL cursorsを使用することができます。

cur.execute("declare foo cursor for select * from generate_series(1,1000000)") 
cur.execute("fetch forward 100 from foo") 
rows = cur.fetchall() 
# ... 
cur.execute("fetch forward 100 from foo") 
rows = cur.fetchall() 
# and so on 
+0

しかし、私はすでにカーソルを使用しています。上のコードを見たことがありますか? – user1919

+0

@ user1919はい、見ました。しかし、サーバー側のカーソルは開くと高速になります。いずれにしてもあなたには選択肢があります。両方の方法を試してください: 'fetchmany()'。 – Abelisto

+1

Hmm。そうですか。しかし、この回答に基づいて私はすでにサーバー側のカーソルを使用していると思った:http://stackoverflow.com/questions/28343240/psycopg2-uses-up-memory-on-large-select-query – user1919

1

Psycopg2は、サーバー側のカーソルを操作するための素敵なインターフェイスを持っています。

with psycopg2.connect(database_connection_string) as conn: 
    with conn.cursor(name='name_of_cursor') as cursor: 

     cursor.itersize = 20000 

     query = "SELECT * FROM ..." 
     cursor.execute(query) 

     for row in cursor: 
      # process row 

上記のコードは、接続を作成し、自動的にクエリ結果をサーバー側のカーソルに配置します。値itersizeは、クライアントがサーバー側カーソルから一度にプルダウンする行数を設定します。使用する値は、ネットワークコールの数とクライアントのメモリ使用量のバランスを取る必要があります。たとえば、結果が300万件の場合、itersizeの値が2000(デフォルト値)の場合、1500回のネットワークコールが発生します。 2000行で消費されるメモリが軽い場合は、その数を増やします。

for row in cursorを使用している場合は、一度に1行ずつ作業しますが、Psycopg2は一度にitersize行をプリフェッチします。

あなたには、いくつかの理由でfetchmanyを使用したい場合は、あなたがこのような何かを行うことができます:

while True: 
    rows = cursor.fetchmany(100) 
    if len(rows) > 0: 
     for row in rows: 
      # process row 
    else: 
     break 

プリフェッチバッチがされるまでfetchmanyのこの使用法は、複数の行のために、サーバへのネットワーク呼び出しをトリガしません。疲れた。 (これは上のコードを何も提供しない複雑な例ですが、必要があればfetchmanyを使用する方法を示しています)。

関連する問題