对于Google App Engine(java),如何在FetchOptions中设置和使用块大小?

时间:2011-08-26 00:22:03

标签: java google-app-engine google-cloud-datastore chunking

我正在运行一个查询,它当前正在返回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);

我在这里找到了以下两个条目:

但实际上并未涉及有关如何实施或使用这些选项的任何细节。 我猜它是一个服务器端进程,我猜你是想设置某种循环来一次抓取一个块,但我该怎么做呢?

  • 我是否在循环中调用查询?
  • 我怎么知道要循环多少次?
  • 我只是检查第一个以小于块大小的条目数返回的块?

如果没有一个实际的例子,我是怎么想找到这样的东西? 在我看来,这里的其他人似乎“只知道”该怎么做..!

抱歉,如果我没有以正确的方式提问,或者我只是一个愚蠢的新手,但是我不知道还有什么可以解决这个问题!

3 个答案:

答案 0 :(得分:4)

遇到同样的问题,最后一条评论来自一个月前,所以这里是我发现的重型数据集查询。

我想在阅读google docs article中的那些行之后我会使用“查询光标”技术(顺便提到的python中的那一行):

  

本文是为SDK 1.1.7版编写的。截至1.3.1版,   查询游标(Java | Python)已取代所描述的技术   下面是现在推荐的大型分页方法   数据集。

在关于“Query Cursor”的Google文档中。 doc的第一行正是为什么需要 cursor

  

查询游标允许应用程序执行查询并检索一批查询   结果,然后在a中获取同一查询的其他结果   后续网站请求,没有查询偏移的开销

该文档还提供了使用游标技术的servlet的 java示例。有一个提示如何为客户端生成一个安全的游标。最后,公开了 cursor 的限制。

希望这能帮助您解决问题。

关于范围和偏移的小提醒,如果忘记(我做了^^),对性能影响相当大:

  

起始偏移对性能有影响:数据存储   必须在开始之前检索并丢弃所有结果   偏移。例如,范围为5,10的查询会获取10个结果   从数据存储区,然后丢弃前五个并返回   剩下五个申请。


编辑:在使用JDO时,我一直在寻找一种方法来允许我以前的代码在单个查询中加载超过1000个结果。所以,如果你也使用JDO,我发现这个旧的issue

Query query = pm.newQuery(...);
// I would use of value below 1000 (gae limit) 
query.getFetchPlan().setFetchSize(numberOfRecordByFetch); 

答案 1 :(得分: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)。

如果我的答案不是你想要的,那么欢迎你重新提出你的问题(编辑)。

顺便说一下,我是编写第一个链接问题的人。

答案 2 :(得分:1)

如果您直接使用dataStore,没有 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)) {
    ...
}