PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

MemoryError при използване на метода read() при четене на JSON файл с голям размер от Amazon S3

Могат да бъдат постигнати значителни спестявания, като се избегне прехвърлянето на целия ви входен файл в паметта като list от линии.

По-конкретно, тези редове са ужасни за използване на паметта, тъй като включват пиково използване на паметта от bytes обект на размера на целия ви файл, плюс list от редове и с пълното съдържание на файла:

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

За 1 GB ASCII текстов файл с 5 милиона реда, на 64-битов Python 3.3+, това е максимално изискване за памет от приблизително 2,3 GB за само bytes обект, list и отделния str s в list . Програма, която се нуждае от 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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. не мога да се свържа с Postgres (pg) база данни от моя Ruby Script, използвайки gem pg (Това не са релси, просто чист рубин)

  2. Наименуване на всеки ред в таблицата с произволен низ от 2 думи

  3. Вмъкване на текст с единични кавички в PostgreSQL

  4. Основно наблюдение на PostgreSQL – част 3

  5. Как Extract() работи в PostgreSQL