7

Google App Engine には適切なサイズのデータ​​ベース (50,000 を超えるエンティティ) があり、そこから古いデータを消去したいと考えています。計画は、不要になったエンティティを繰り返し処理する遅延タスクを作成し、それらをバッチで削除することでした。

厄介なことの 1 つは、エンティティには削除したい子エンティティもあるということです。これは問題ありません。これらのエンティティのデータストアをクエリし、親と同時にドロップします。

query = ParentKind.all()
query.count(100)
query.filter('bar =', 'foo')
to_delete = []
for entity in enumerate(query):
    to_delete.append(entity)
    to_delete.extend(ChildKindA.all().ancestor(entity).fetch(100))
    to_delete.extend(ChildKindB.all().ancestor(entity).fetch(100))
db.delete(to_delete)

ParentKind一度に 100 個のエンティティを削除するように制限しました。それぞれParentKindに合計で約 40 の子ChildKindAChildKindBエンティティがあり、おそらく 4000 のエンティティでした。

これは当時は合理的と思われましたが、テストとして 1 つのバッチを実行したところ、結果のクエリの実行に 9 秒かかり、データストアへのアクセスに課金対象の CPU 時間で1933秒が費やされました。

これはかなり厳しいように思えます -- エンティティごとに 0.5 秒の請求が可能です! -- しかし、何が間違っているのか完全にはわかりません。それは単にバッチのサイズですか?祖先クエリは特に遅いですか? それとも、削除 (および実際にはすべてのデータストア アクセス) が単に糖蜜のように遅いのでしょうか?

アップデート

クエリを に変更しました。keys_onlyこれにより、1 つのバッチの実行時間が 4.5 秒に短縮されましたが、それでも CPU 時間は約 1900 秒かかりました。

次に、Appstats をアプリにインストールし (ありがとう、kevpie)、より小さいサイズのバッチを実行しました。10 個の親エンティティで、合計で最大 450 個のエンティティになります。更新されたコードは次のとおりです。

query = ParentKind.all(keys_only=True)
query.count(10)
query.filter('bar =', 'foo')
to_delete = []
for entity in enumerate(query):
    to_delete.append(entity)
    to_delete.extend(ChildKindA.all(keys_only=True).ancestor(entity).fetch(100))
    to_delete.extend(ChildKindB.all(keys_only=True).ancestor(entity).fetch(100))
db.delete(to_delete)

Appstats の結果:

service.call           #RPCs  real time  api time
datastore_v3.RunQuery  22     352ms      555ms
datastore_v3.Delete    1      366ms      132825ms
taskqueue.BulkAdd      1      7ms        0ms

Delete呼び出しは、操作の中で最もコストのかかる部分です。

これを回避する方法はありますか?Nick Johnson 氏は、現時点では一括削除ハンドラを使用するのが最速の削除方法であると述べましたが、理想的には、同じ種類のすべてのbar = fooエンティティを削除するのではなく、最初のクエリに一致し、その子であるエンティティだけを削除したいと考えています。

4

2 に答える 2

2

最近、ここに記載されている一括削除ハンドラーを追加しました。CPU クォータを消費しますが、一括削除には最も効率的なアプローチが取られます。

于 2010-12-15T22:09:56.897 に答える
1

CPU の消費を分散させたい場合は、マップ削減ジョブを作成できます。すべてのエンティティを繰り返し処理します (これはマッパー API の現在の制限です)。ただし、各エンティティが条件を満たしているかどうかを確認し、その時点で削除するかどうかを確認できます。

CPU 使用率を下げるには、通常よりも遅く実行するように構成したタスク キューにマッパーを割り当てます。実行時間を数日間に分散して、CPU クォータを使い果たすことはありません。

于 2010-12-16T19:27:53.360 に答える