sql >> Database teknologi >  >> RDS >> PostgreSQL

Hukommelsesfejl ved brug af read()-metoden ved læsning af en stor størrelse af JSON-fil fra Amazon S3

En betydelig besparelse kan opnås ved at undgå at slurre hele din inputfil i hukommelsen som en list af linjer.

Specifikt er disse linjer forfærdelige med hensyn til hukommelsesbrug, idet de involverer en maksimal hukommelsesbrug på bytes objekt størrelsen af ​​hele din fil, plus en list af linjer med det komplette indhold af filen også:

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

For en 1 GB ASCII-tekstfil med 5 millioner linjer, på 64 bit Python 3.3+, er det et maksimalt hukommelseskrav på ca. 2,3 GB for kun bytes objekt, list , og den individuelle str s på list . Et program, der har brug for 2,3 gange så meget RAM som størrelsen af ​​de filer, det behandler, skaleres ikke til store filer.

For at rette, skal du ændre den originale kode til:

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

I betragtning af at obj['Body'] ser ud til at kunne bruges til dovne streaming dette burde fjerne begge kopier af de komplette fildata fra hukommelsen. Brug af TextIOWrapper betyder obj['Body'] læses dovent og afkodes i bidder (af nogle få KB ad gangen), og linjerne gentages også dovent; dette reducerer hukommelsesbehovet til et lille, stort set fast beløb (den maksimale hukommelsesomkostning vil afhænge af længden af ​​den længste linje), uanset filstørrelsen.

Opdatering:

Det ligner StreamingBody implementerer ikke io.BufferedIOBase ABC. Den har sin egen dokumenterede API det kan dog bruges til et lignende formål. Hvis du ikke kan lave TextIOWrapper gøre arbejdet for dig (det er meget mere effektivt og enkelt, hvis det kan fås til at fungere), et alternativ ville være at gøre:

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

I modsætning til at bruge TextIOWrapper , den har ikke gavn af masseafkodning af blokke (hver linje afkodes individuelt), men ellers skulle den stadig opnå de samme fordele i form af reduceret hukommelsesforbrug.




  1. Er det muligt at have en standardparameter for en mysql-lagret procedure?

  2. MySQL - Er det muligt at bruge LIKE på alle kolonner i en tabel?

  3. Gendan mysql-databasen fra .frm-filer

  4. Optimering af Oracle-forespørgsel