10

クエリを実行していて、現在 1400 件の結果が返されているため、ログ ファイルに次の警告が表示されます。

com.google.appengine.api.datastore.QueryResultsSourceImpl logChunkSizeWarning: このクエリには FetchOptions で設定されたチャンク サイズがなく、1000 を超える結果が返されました。このサイズの結果セットがこのクエリで一般的である場合は、チャンク サイズを設定してパフォーマンスを向上させることを検討してください。

これを実際に実装する方法についての例はどこにも見つかりません。Pythonについてここに質問がありますが、Javaを使用していてPythonを理解していないため、翻訳に苦労しています。

また、このクエリ (以下) の実行には 17226cpu_ms かかりますが、これは長すぎるように感じます。5000 件の連絡先があり、クライアント側でそれらを検索する必要があるとしたらどうなるか想像できません (googlemail の連絡先のように! )

私が持っているコードは次のとおりです。

    int index=0;
    int numcontacts=0;
    String[][] DetailList;

    PersistenceManager pm = PMF.get().getPersistenceManager();


    try {
        Query query = pm.newQuery(Contact.class, "AdminID == AID");
        query.declareParameters("Long AID");
        query.setOrdering("Name asc");
        List<Contact> Contacts = (List<Contact>) query.execute(AdminID);
        numcontacts=Contacts.size();
        DetailList=new String[numcontacts][5];

        for (Contact contact : Contacts) 
        {
            DetailList[index][0]=contact.getID().toString();
            DetailList[index][1]=Encode.EncodeString(contact.getName());
            index++;
        }
    } finally {
        pm.close();
    }
    return (DetailList);

ここで次の2つのエントリを見つけました。

ただし、これらのオプションを実装または使用する方法については、実際には詳しく説明していません。私はそれがサーバー側のプロセスであると推測しており、一度に1つのチャンクを取得するためにある種のループをセットアップすることを意図していると推測していますが、実際にそれを行うにはどうすればよいですか?

  • ループ内でクエリを呼び出しますか?
  • ループする回数を知るにはどうすればよいですか?
  • チャンク サイズよりも少ない数のエントリが返された最初のチャンクをチェックするだけですか?

実際の例に従わずに、このようなものを見つけようとするつもりはありませんか? ここにいる他の人たちは、やり方を「知っている」ように思えます..!

申し訳ありませんが、私が正しい方法で質問をしていない場合、または私がこれについてぼんやりした初心者である場合は、これを理解するために他にどこに頼ればよいかわかりません!

4

3 に答える 3

4

同じ問題に対応し、最後のコメントは1か月前のものだったので、重いデータセットクエリについて私が見つけたものは次のとおりです。

google docsの記事(ちなみにPythonで言及されているもの)のこれらの行を読んだ後、「クエリカーソル」テクニックを使用するつもりだと思います:

この記事はSDKバージョン1.1.7用に書かれています。リリース1.3.1の時点で、クエリカーソル(Java | Python)は、以下で説明する手法に取って代わり、大規模なデータセットをページングするための推奨される方法になりました。

「クエリカーソル」に関するGoogleドキュメント。ドキュメントの最初の行は、カーソルが必要な理由を正確に示しています。

クエリカーソルを使用すると、アプリはクエリを実行して結果のバッチを取得し、クエリオフセットのオーバーヘッドなしで、後続のWebリクエストで同じクエリの追加の結果をフェッチできます。

ドキュメントには、カーソル技術を使用したサーブレットのJavaの例も記載されています。クライアント用の安全なカーソルを生成する方法のヒントがあります。最後に、カーソルの制限が明らかになります。

これがあなたの問題を解決するための手がかりになることを願っています。

範囲とオフセットについての小さなリマインダー。忘れるとパフォーマンスにかなり影響します(そして私はそうしました^^):

開始オフセットはパフォーマンスに影響を及ぼします。データストアは、開始オフセットの前にすべての結果を取得して破棄する必要があります。たとえば、範囲が5、10のクエリは、データストアから10個の結果をフェッチし、最初の5個を破棄して、残りの5個をアプリケーションに返します。


編集:JDOを使用して作業しているときに、以前のコードで1000を超える結果を1つのクエリでロードできるようにする方法を探し続けました。したがって、JDOも使用している場合は、この古い問題が見つかりました。

Query query = pm.newQuery(...);
// I would use of value below 1000 (gae limit) 
query.getFetchPlan().setFetchSize(numberOfRecordByFetch); 
于 2012-08-18T00:04:25.660 に答える
3

これは私が適用する方法ですFetchOptions。サンプルコードと比較して、少し調整する必要があるかもしれません:

// ..... build the Query object
FetchOptions fetch_options =
    FetchOptions.Builder.withPrefetchSize(100).chunkSize(100);
QueryResultList<Entity> returned_entities =
    datastore_service_instance.prepare(query).asQueryResultList(fetch_options);

もちろん、数値は変更される可能性があります (100)。

私の答えがあなたが探しているものではない場合は、質問を言い換えてください (編集)。

ちなみに、最初のリンクされた質問を書いたのは私です。

于 2011-08-28T13:26:24.900 に答える
1

JDOを使用せずにデータストアを直接使用している場合は、次のようにして、データを反復処理するときにチャンクサイズを設定します。

Query query = new Query("entityname");
PreparedQuery preparedQuery = dataStore.prepare(query);
// the 200 should be less than 1000
FetchOptions options = FetchOptions.Builder.withChunkSize(200);
for (Entity result : preparedQuery.asIterable(options)) {
    ...
}
于 2012-09-06T21:43:00.740 に答える