Melhore o rendimento da consulta ndb em dados grandes

Estou tentando executar algum processamento de dados em um aplicativo GAE sobre dados armazenados no armazenamento de dados. O ponto de gargalo é a taxa de transferência na qual a consulta retorna entidades e eu me pergunto como melhorar o desempenho da consulta.

O que eu faço em geral:

tudo funciona em uma fila de tarefas, por isso temos bastante tempo (prazo de 10 minutos).Eu executo uma consulta sobre as entidades ndb para selecionar quais entidades precisam ser processadas.À medida que a consulta retorna resultados, agrupo entidades em lotes de, digamos, 1000 e os envio para outra fila de tarefas para processamento adicional.os dados armazenados serão grandes (por exemplo, entidades de 500 mil a 1 milhão) e há uma chance de que o prazo de 10 minutos não seja suficiente. Portanto, quando a tarefa atinge o prazo da fila de tarefas, gera uma nova tarefa. Isso significa que eu preciso de um ndb.Cursor para continuar a consulta de onde parou.

O problema é a taxa na qual a consulta retorna entidades. Eu tentei várias abordagens e observei o seguinte desempenho (que é muito lento para o meu aplicativo):

Use fetch_page () em um loop while.

O código é direto

while has_more and theres_more_time:
 entities, cursor, more = query.fetch_page(1000, ...)
 send_to_process_queue(entities)
 has_more = more and cursor

Com essa abordagem, leva de 25 a 30 segundos para processar 10 mil entidades. Grosso modo, são 20 mil entidades por minuto. Tentei alterar o tamanho da página ou a classe da instância do frontend; nenhum deles fez diferença no desempenho.

Segmente os dados e dispare vários fetch_page_async () em paralelo.

Esta abordagem é tomada a partir daqui (abordagem C)

O desempenho geral permanece o mesmo que acima. Eu tentei com vários números de segmentos (de 2 a 10) para ter 2-10 chamadas paralelas em fetch_async (). Em todos os casos, o tempo total permaneceu o mesmo. Quanto mais paralelo for chamado fetch_page_async (), mais tempo leva para que cada um seja concluído. Eu também tentei com 20 buscas paralelas e ficou pior. Alterar o tamanho da página ou a classe de instância com frente também não teve e teve impacto.

Busque tudo com uma única chamada fetch ().

Agora, essa é a abordagem menos adequada (se não for inadequada), pois a instância pode ficar sem memória, além disso, não recebo um cursor caso precise gerar outra tarefa (na verdade, nem sequer tenho o capacidade de fazê-lo, a tarefa simplesmente excederá o prazo). Tentei isso por curiosidade, para ver como ele funciona e observei o melhor desempenho! Foram necessários 8 a 10 segundos para 10 mil entidades, o que equivale a aproximadamente 60 mil entidades por minuto. Agora isso é aprox. 3 vezes mais rápido que fetch_page (). Eu me pergunto por que isso acontece.

Use query.iter () em um único loop.

Isso é parecido com a primeira abordagem. Isso fará uso do gerador subjacente do iterador de consulta, além de poder obter um cursor do iterador, caso precise gerar uma nova tarefa, para que ela se adapte a mim. Com o iterador de consulta, ele buscou 10.000 entidades em 16 a 18 segundos, o que é aprox. 36 a 40 mil entidades por minuto. O iterador é 30% mais rápido que fetch_page, mas muito mais lento que fetch ().

Para todas as abordagens acima, tentei instâncias de front-end F1 e F4 sem nenhuma diferença no desempenho do armazenamento de dados. Também tentei alterar o parâmetro batch_size nas consultas, ainda sem nenhuma alteração.

Uma primeira pergunta é por que fetch (), fetch_page () e iter () se comportam de maneira tão diferente e como fazer com que fetch_page () ou iter () funcionem tão bem quanto fetch ()? E outra questão crítica é se essas taxas de transferência (20 a 60 K entidades por minuto, dependendo da chamada da API) são as melhores que podemos fazer no GAE.

Estou ciente da API do MapReduce, mas acho que ela não combina comigo. AFAIK, a API MapReduce não oferece suporte a consultas e não quero varrer todas as entidades do armazenamento de dados (será muito caro e lento - a consulta pode retornar apenas alguns resultados). Por último, mas não menos importante, tenho que seguir o GAE. Recorrer a outra plataforma não é uma opção para mim. Portanto, a questão é realmente como otimizar a consulta ndb.

Alguma sugestão?

questionAnswers(3)

yourAnswerToTheQuestion