Как установить и использовать размер чанка в FetchOptions для Google App Engine (Java)? - PullRequest
10 голосов
/ 26 августа 2011

Я выполняю запрос, и в настоящее время он возвращает 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 ]

4 голосов
/ 18 августа 2012

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

Полагаю, я собираюсь использовать технику "Курсор запроса" после прочтенияэти строки в google docs статье (ту, что упоминается в python, упомянутую кстати):

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

В Google Docs о " Query Cursor ".В первой строке документа объясняется, почему именно курсор :

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

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

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

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

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


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

Query query = pm.newQuery(...);
// I would use of value below 1000 (gae limit) 
query.getFetchPlan().setFetchSize(numberOfRecordByFetch); 
3 голосов
/ 28 августа 2011

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

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

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

1 голос
/ 07 сентября 2012

Если вы используете хранилище данных напрямую, без 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)) {
    ...
}
...