Для Google App Engine (java), как установить и использовать размер блока в FetchOptions?

Im запускает запрос и в настоящее время возвращает 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);

Здесь я нашел следующие две записи:

но ни одна из них не содержит подробных сведений о том, как реализовать или использовать эти параметры. Я предполагаю, что это процесс на стороне сервера, и я предполагаю, что вы собираетесь настроить какой-то цикл, чтобы захватить куски на один кусок за раз, но как я на самом деле это делаю?

  • Я вызываю запрос внутри цикла?
  • Как узнать, сколько раз цикл?
  • Я просто проверяю первый кусок, который возвращается с меньшим количеством записей в количестве блоков?

Как я собирался разобраться с такими вещами без фактического примера? Мне кажется, что другие люди здесь, похоже, "просто знают", как это сделать..!

Извините Если я не задаю вопросы правильно, или я просто тусклый новичок по этому поводу, но я не знаю, куда еще обратиться, чтобы понять это!

Ответ 1

Встречая ту же проблему, и последний комментарий был сделан месяц назад, поэтому вот что я узнал о тяжелом запросе набора данных.

Я предполагаю, что после использования этих строк в документах google article (тот, что в питон, упомянутый кстати):

Эта статья была написана для версии SDK версии 1.1.7. Начиная с версии 1.3.1, курсоры запросов (Java | Python) имеют вытеснили описанные методы ниже и теперь является рекомендуемым методом подкачки через большие наборы данных.

В документах google о "Курсор курсора ". Первая строка документа дает именно то, зачем нужна курсор:

Курсоры запросов позволяют приложению выполнять запрос и получать пакет результатов, затем получить дополнительные результаты для одного и того же запроса в последующий веб-запрос без накладных расходов смещения запроса.

В документации также представлен пример java сервлета с использованием техники курсора. Есть подсказка, как создать безопасный курсор для клиента. Наконец, раскрываются ограничения курсора.

Надеюсь, это поможет вам решить вашу проблему.

Небольшое напоминание о диапазоне и смещение, что сильно влияет на производительность, если забыто (и я сделал ^^):

Начальное смещение имеет последствия для производительности: хранилище данных должен извлекать и затем отбрасывать все результаты до начала смещение. Например, запрос с диапазоном 5, 10 выводит десять результатов из хранилища данных, затем отбрасывает первые пять и возвращает оставшиеся пять приложений.


Изменить: работая с JDO, я продолжал искать способ, чтобы мой предыдущий код загружал более 1000 результатов в один запрос. Итак, если вы используете JDO, я нашел этот старый issue:

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

Ответ 2

Вот как я применяю 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).

Если мой ответ не тот, который вы ищете, тогда вы можете перефразировать свой вопрос (отредактировать).

Кстати, я тот, кто написал первый связанный вопрос.

Ответ 3

Если вы используете 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)) {
    ...
}