Google データストア内の 10 万以上のエンティティの場合、ndb.query().count() は、インデックスを使用しても、deadline までにキャンセルされます。私は Produce_cursors オプションを試しましたが、iter() または fetch_page() のみがカーソルを返しますが、count() は返しません。
大きなエンティティをカウントするにはどうすればよいですか?
Google データストア内の 10 万以上のエンティティの場合、ndb.query().count() は、インデックスを使用しても、deadline までにキャンセルされます。私は Produce_cursors オプションを試しましたが、iter() または fetch_page() のみがカーソルを返しますが、count() は返しません。
大きなエンティティをカウントするにはどうすればよいですか?
高価なことをするには、Task Queue Python APIを見てください。Task Queue API に基づいて、Google App Engine はdeferred ライブラリを提供します。これを使用して、バックグラウンド タスクの実行プロセス全体を簡素化できます。
アプリで遅延ライブラリを使用する方法の例を次に示します。
import logging
def count_large_query(query):
total = query.count()
logging.info('Total entities: %d' % total)
次に、アプリ内から上記の関数を次のように呼び出すことができます。
from google.appengine.ext import deferred
# Somewhere in your request:
deferred.defer(count_large_query, ndb.query())
count()
このような大規模なデータストアで結果が返されるかどうかはまだわかりませんがcount_large_query()
、代わりにカーソルを使用するこの関数を使用できます (未テスト):
LIMIT = 1024
def count_large_query(query):
cursor = None
more = True
total = 0
while more:
ndbs, cursor, more = query.fetch_page(LIMIT, start_cursor=cursor, keys_only=True)
total += len(ndbs)
logging.info('Total entitites: %d' % total)
上記をローカルで試すには、LIMIT
を 4 に設定し、コンソールに行が表示されるかどうかを確認しますTotal entitites: ##
。
Guido がコメントで述べたように、これもスケーリングされません。
これはまだスケーリングしません (問題を先延ばしにする可能性はありますが)。タスクは 1 分ではなく 10 分なので、10 倍の数のエンティティを数えることができます。しかし、それはかなり高価です!これを適切に解決したい場合は、シャードされたカウンターを検索してください (残念ながら、それは大変な作業です)。
そのため、スケーラブルなアプリケーション、特にシャーディング カウンターを作成するためのベスト プラクティスを確認することをお勧めします。
これは実に悩ましい問題です。最近、この分野でいくつかの作業を行って、一般的なカウント統計を取得しています。基本的には、クエリを満たすエンティティの数です。count()
これは素晴らしいアイデアですが、データストアの RPC タイムアウトによって妨げられています。
count()
キーの大きなリストを返すだけでそれらを捨てるのではなく、結果セット全体にカーソルを合わせて、結果の整数を単純に合計できるように、カーソルが何らかの形でサポートされていると便利です。カーソルを使用すると、「バトンを渡す」遅延アプローチを使用して、すべての 1 分 / 10 分の境界を越えて続行できます。count()
( とは対照的に) を使用fetch(keys_only=True)
すると、浪費を大幅に削減でき、できれば RPC 呼び出しの速度を向上させることができます。たとえば、このfetch(keys_only=True)
アプローチを使用すると 1,000,000 までカウントするのに驚くほどの時間がかかります。
定期的なカウント統計 (たとえば、国ごとのシステム内のすべてのアカウントの毎日のカウントなど) のみが必要な場合、または必要な場合、シャードされたカウンターは多くのオーバーヘッドになります。
Google App Engine バックエンドを使用することをお勧めします。バックエンドは、ユーザー リクエストの 60 秒の期限とタスクの 10 分の期限から免除され、無期限に実行されます。こちらのドキュメントをご覧ください: https://developers.google.com/appengine/docs/java/backends/overview