sql >> Databáze >  >> RDS >> PostgreSQL

Chyba paměti při použití metody read() při čtení velké velikosti souboru JSON z Amazon S3

Významné úspory lze dosáhnout tím, že se vyhnete tomu, že celý vstupní soubor budete dávat do paměti jako list řádků.

Konkrétně tyto řádky jsou hrozné na využití paměti, protože zahrnují maximální využití paměti bytes objekt velikosti celého vašeho souboru plus list řádků s úplným obsahem souboru:

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

Pro 1 GB textový soubor ASCII s 5 miliony řádků v 64bitovém Pythonu 3.3+ to představuje špičkový požadavek na paměť zhruba 2,3 GB za jen bytes objekt, list a jednotlivé str s v list . Program, který potřebuje 2,3x více paměti RAM, než je velikost souborů, které zpracovává, se nebude škálovat na velké soubory.

Chcete-li to opravit, změňte původní kód na:

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

Vzhledem k tomu, že obj['Body'] se zdá být použitelný pro líné streamování toto by mělo odstranit obojí kopie úplných dat souboru z paměti. Pomocí TextIOWrapper znamená obj['Body'] se líně čte a dekóduje po částech (několik KB najednou) a řádky se také líně iterují; to snižuje nároky na paměť na malé, převážně pevné množství (špičková cena paměti by závisela na délce nejdelšího řádku), bez ohledu na velikost souboru.

Aktualizace:

Vypadá to jako StreamingBody neimplementuje io.BufferedIOBase ABC. Má své vlastní zdokumentované API i když to lze použít pro podobný účel. Pokud nemůžete vytvořit TextIOWrapper dělat práci za vás (je to mnohem efektivnější a jednodušší, pokud se to dá udělat), alternativou by bylo udělat:

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

Na rozdíl od použití TextIOWrapper , netěží z hromadného dekódování bloků (každý řádek je dekódován samostatně), ale jinak by měl stále dosahovat stejných výhod ve smyslu snížení využití paměti.




  1. Funkce NUMTODSINTERVAL() v Oracle

  2. Nově přiřazená sekvence nefunguje

  3. ORA-00904 neplatný identifikátor na dekódovacím aliasu

  4. Jaký je ekvivalent PostgreSQL pro ISNULL()