2017-06-26 6 views
0

Rubyを使用してPostgreSQL DBからローをフェッチしています。 pg宝石のサイト(https://deveiate.org/code/pg/PG/Result.htmlRubyとPostgreSQLのシングルローモード

conn.send_query("first SQL query") 
conn.set_single_row_mode 
conn.get_result.stream_each do |row| 
    # do something with the received row of the first query 
end 

に説明したように、これは、単一の行モードで実行されて、私は期待通りに分けて、結果セットのすべての行を取得します。しかし、大きな結果セットの場合、Rubyはそれらを記憶に残しているようです。これにより、Rubyプログラムがメモリ不足になると終了します。

既に処理された行のスペースを解放する方法はありますか? 私はclear()またはautoclear?を使用すべきだと思いますが、私はそれをどのように使用するのか正確に何を明確にするべきかはわかりません。

+0

LIMITOFFSETを追加)承認使用してみてください多分それはメモリ内の行を保持しているpostgresのではないのですが、あなたのコード? –

+0

私はそれがポストグルではないと確信しています。私はそれが私のコードかpgの宝石のどちらかであると思う – maax

+0

私は質問がそれはPgの宝石であると推測し、私はいくつかの代替案を使用することができますか、または宝石が問題なく、私のcideが間違っている場合 – maax

答えて

0

find_each

limit = 1000 
offset = 0 

while do 
    conn.send_query("SELECT * FROM users LIMIT #{limit} OFFSET #{offset}") 
    conn.set_single_row_mode 
    records = conn.get_result 

    if records.any? 
    limit += 1000 
    offset += 1000 
    sleep(5) 
    else 
    break 
    end 
    records.stream_each do |row| 
    # do something with the received row of the first query 
    end 
end 
+0

これはうまくいく、私が直面している唯一の問題は、私に重複する行を与え、いくつかの行を見逃す行を並べ替えることです。 – maax

+0

私はオフセットと制限を使用せずにそれを行うために使用することができますpg gemを使っているかもしれません - おそらく私が知らない別のものがありますか?)、または制限とオフセットで動作する私のpostgres設定を変更しなければならない場合 – maax

+0

@maaxあなたは 'ORDER BY id'を追加してレコードを注文することができます。あなたのメモリリークはrubyコードで表示されます(postgresサーバではありません)。 Rubyは重いガベージコレクタを持っているので。これは、可能な限り無限のレコードコレクションを扱うためにRailsチームが提案するアプローチです。あなたはそれがそこでどのように解決されたか確認することができます:https://github.com/rails/rails/blob/master/activerecord/lib/active_record/relation/batches.rb#L194 – itsnikolay

0

autoclear?オプションがtrueを返さない限り、clear()に電話する必要があります。そうしないと、メモリリークが発生します。十分な大きさの結果セットがある場合は、手動でクリアすることもできます。

親切にこのリンク

https://deveiate.org/code/pg/PG/Result.html

グッドラックとのチェックを持っています!

+0

_whole_結果をクリアしませんか?過去の__and__の未来の行ですか? –

+0

私が知る限り、すべてがクリアされます。私の結果が大きすぎてメモリに収まらず、別のクエリに分割することができないので、それはまさに私の問題です。 – maax