Как предотвратить несколько вызовов RPC RunQuery для одного JDO Query execute ()? - PullRequest
3 голосов
/ 01 ноября 2011

Я настроил Appstats в своем приложении Java Appengine и заметил, что один JDO-запрос, который возвращает несколько объектов, приводит к отдельному RPC-вызову RunQuery для каждого объекта, полученного Query.

Не следует ли выполнять запрос за один вызов RPC?

Я пытался настроить Fetchgroups и Fetchplans, чтобы попытаться избежать этого, но безрезультатно.

Мой код примерно такой:

Query query = pm.newQuery(WidgetDSO.class);

String filter = "widgetId == param1 || widgetId == param2 || widgetId == param3";
String parameters = "String param1, String param2, String param3";

query.setFilter(filter.toString());
query.declareParameters(parameters.toString());

List<WidgetDSO> results = (List<WidgetDSO>) query.executeWithArray(widgetIds);
if (!results.isEmpty()) 
...

Когда это запускается, Appstats сообщает мне, что последняя строка results.isEmpty() приводит к тому, что столько вызовов RPC, сколько извлеченных объектов:

@104ms datastore_v3.RunQuery real=5ms api=21ms
@422ms datastore_v3.RunQuery real=4ms api=12ms
@428ms datastore_v3.RunQuery real=4ms api=12ms
@434ms datastore_v3.RunQuery real=3ms api=12ms
@439ms datastore_v3.RunQuery real=4ms api=12ms
@445ms datastore_v3.RunQuery real=4ms api=12ms
@451ms datastore_v3.RunQuery real=4ms api=21ms
@463ms datastore_v3.RunQuery real=5ms api=21ms

Трассировка стека для каждого из этих вызовов одинакова (только частичная трассировка стека):

com.google.appengine.tools.appstats.Recorder:290 makeAsyncCall()
com.google.apphosting.api.ApiProxy:184 makeAsyncCall()
com.google.appengine.api.datastore.DatastoreApiHelper:81 makeAsyncCall()
com.google.appengine.api.datastore.PreparedQueryImpl:144 runQuery()
com.google.appengine.api.datastore.PreparedQueryImpl:70 asIterator()
com.google.appengine.api.datastore.PreparedMultiQuery$FilteredMultiQueryIterator:165 getNextIterator()
com.google.appengine.api.datastore.PreparedMultiQuery$FilteredMultiQueryIterator:184 computeNext()
com.google.appengine.api.datastore.PreparedMultiQuery$FilteredMultiQueryIterator:98 computeNext()
com.google.appengine.api.datastore.AbstractIterator:52 tryToComputeNext()
com.google.appengine.api.datastore.AbstractIterator:47 hasNext()
com.google.appengine.api.datastore.BasePreparedQuery$UncompilablePreparedQuery$1:86 hasNext()
org.datanucleus.store.appengine.query.RuntimeExceptionWrappingIterator$1:50 get()
org.datanucleus.store.appengine.query.RuntimeExceptionWrappingIterator$1:46 get()
org.datanucleus.store.appengine.query.QueryExceptionWrappers$1:51 get()
org.datanucleus.store.appengine.query.QueryExceptionWrappers$2:86 get()
org.datanucleus.store.appengine.query.RuntimeExceptionWrappingIterator:105 hasNext()
org.datanucleus.store.appengine.query.LazyResult:115 resolveAll()
org.datanucleus.store.appengine.query.LazyResult:110 size()
org.datanucleus.store.appengine.query.StreamingQueryResult:130 size()
org.datanucleus.store.query.AbstractQueryResult:312 isEmpty()
org.instantplaces.im.server.dso.WidgetDSO:209 getWidgetsFromDSO()
org.instantplaces.im.server.resource.WidgetResource:239 doDelete()
org.instantplaces.im.server.resource.GenericResource:244 delete()

Есть ли способ получить все объекты за один вызов?

1 Ответ

2 голосов
/ 01 ноября 2011

Это ваш точный код?Если так, то я бы ожидал как минимум 3 запроса, минимум.Там нет родного "||"(«ИЛИ») в хранилище данных.JDO вынужден переводить ваш запрос в один запрос для каждой опции.Для получения дополнительной информации см. документы и соответствующее сообщение в блоге .Это не указано прямо - вам нужно объединить тот факт, что || превращаются в .contains (), а .contains () требует многократного получения.

||допустимо только в тех случаях, когда разделяемые фильтры могут быть объединены в один фильтр contains ():

и

Оператор contains () также выполняет несколько запросов,по одному для каждого элемента в предоставленном значении списка, где все остальные фильтры одинаковы, а фильтр contains () заменен фильтром, равным равному.

...