2015-05-29 1 views
0

Как читать и писать большое количество (~ 1 млн.) Объектов модели в GAE Python?Как читать и писать большое количество (~ 1 млн.) Объектов модели в GAE Python?

Мои ОПРС Модель:

class X (ndb.Model): 
    Y = ndb.JsonProperty ("a", repeated=True, indexed=False) 
    # max list length = 10. 
    # Example of a list stored in Y above : 
    # Y = [ 
    #  { "n" : "name_p__of_around_100_chars", "s" : number_p__between_0_and_100, "a" : "address_p__of_200_chars" }, 
    #  { "n" : "name_q__of_around_100_chars", "s" : number_q__between_0_and_100, "a" : "address_q__of_200_chars" }, 
    # ] 

мне нужно прочитать объекты из модели "X" и обновить его свойство "Y" и писать обратно в НБД.

Мой первый подход
Читать все объекты с помощью ndb.get_multi (key_list).
Этот подход потерпел неудачу, потому что он ударил предел проблемы памяти в ndb.get_multi():

Превышен предел мягкой собственной памяти 512 Мб с 623 МБ после обслуживающей 1 запрашивает всего

ли кто-нибудь делал это раньше?
Каков наилучший способ сделать это?

Я делаю это внутри очереди TaskQueue Push, чтобы избежать тайм-аутов запроса.

ЧТО МОЯ ПРОБЛЕМА решаемые
Спасибо всем. Я оптимизировал свой алгоритм (который был слишком запутанным раньше) и избавился от проблемы с памятью. Все ваши предложения были очень информативными, но реальной проблемой был мой плохой алго. Поэтому я не могу отметить любой ответ, как принято здесь.

Я оставляю этот вопрос здесь (не удаляя его, даже если это проблема с моим кодом), чтобы кто-то еще мог получить хорошие указатели на проблему утечки памяти на GAE Python.

Спасибо, Дмитрий Садовничий, Дэн Корнилеску и Тим Хоффман.

+1

Использования MapReduce, или .fetch_page с прецессирующими ограниченной партией в одном запросе и создание новой задачи с последующим курсором. –

+0

@DmitrySadovnychyi Спасибо. Я бы попробовал, но GAE не освобождает память после прочтения сущностей довольно долгое время. Я читал множества объектов (скажем, 100), используя 'fetch_page', и запускал задачу TaskQueue для этого набора из 100 объектов. Когда я прочитаю следующий набор из 100 объектов, память (ОЗУ) для более раннего набора из 100 объектов останется. Новая память станет 100 + 100 = 200. – gsinha

+1

Вы можете попробовать позвонить gc.collect –

ответ

1

Вы можете разделить свой key_list на более мелкие куски и пронести через них.

Остерегайтесь того, что TaskQueue также имеет временную квоту, поэтому вы не избегаете просто «любого тайм-аута», вам может потребоваться дальнейшее разделение общей итерации на более мелкие куски.

Я думаю, это могло бы эффективно использовать трубопроводную API для решения масштабируемости - вы можете захотеть взглянуть на этой статье: https://blog.svpino.com/2015/05/19/the-google-app-engine-pipeline-api

Смежные вопросы