sql >> データベース >  >> RDS >> PostgreSQL

Amazon S3から大きなサイズのJSONファイルを読み取る際にread()メソッドを使用する場合のMemoryError

    入力ファイル全体をlistとしてメモリに丸呑みすることを回避することで、大幅な節約が可能になります。 行の。

    具体的には、これらの行は、bytesのピークメモリ使用量を伴うという点で、メモリ使用量に関してひどいものです。 ファイル全体のサイズに加えて、listをオブジェクト化します。 ファイルの完全な内容を含む行の数:

    file_content = obj['Body'].read().decode('utf-8').splitlines(True)
    for line in file_content:
    

    500万行の1GBASCIIテキストファイル(64ビットPython 3.3以降)の場合、これはちょうどのピークメモリ要件である約2.3GBです。 bytes オブジェクト、list 、および個々のstr slist 。処理するファイルのサイズの2.3倍のRAMを必要とするプログラムは、大きなファイルに拡張できません。

    修正するには、元のコードを次のように変更します。

    file_content = io.TextIOWrapper(obj['Body'], encoding='utf-8')
    for line in file_content:
    

    obj['Body'] 怠惰なストリーミングに使用できるようです これにより、両方が削除されます。 メモリからの完全なファイルデータのコピー。 TextIOWrapperの使用 obj['Body']を意味します (一度に数KBの)チャンクで遅延読み取りおよびデコードされ、行も遅延して繰り返されます。これにより、ファイルサイズに関係なく、メモリ需要が小さく、ほぼ固定された量に削減されます(ピークメモリコストは最長の行の長さに依存します)。

    更新:

    StreamingBodyのように見えます io.BufferedIOBaseを実装していません ABC。 独自のドキュメント化されたAPI があります ただし、これは同様の目的で使用できます。 TextIOWrapperを作成できない場合 あなたのために仕事をしてください(それを機能させることができれば、はるかに効率的で簡単です)、別の方法は次のようになります:

    file_content = (line.decode('utf-8') for line in obj['Body'].iter_lines())
    for line in file_content:
    

    TextIOWrapperの使用とは異なり 、ブロックの一括デコード(各行は個別にデコードされます)のメリットはありませんが、それ以外の場合は、メモリ使用量の削減という点で同じメリットが得られるはずです。




    1. SELECTDISTINCTはさまざまなケースを無視します

    2. IDEF1X表記

    3. PostgreSQLのグループ化されたLIMIT:各グループの最初のN行を表示しますか?

    4. PHP-厳格な標準:変数のみを参照で渡す必要があります