I've just started getting the following error on my server. This query
had been working fine for months, and I haven't changed the indexes
lately. Are there some indexes that just buckle under heavy load or
larger data sets? This particular table contains only 242,604 entries.

  The built-in indices are not efficient enough for this query and
your data. Please add a composite index for this query..  An index is
missing but we are unable to tell you which one due to a bug in the
App Engine SDK.  If your query only contains equality filters you most
likely need a composite index on all the properties referenced in
those filters.
  (full stack dump included below)

My query source code:

    Query query = pm.newQuery(GameDataV2.class);
    Object[] params;
    query.declareParameters(
        "com.google.appengine.api.datastore.Key userKeyParam"
        + ", com.honkentuber.wordwise.GameState stateParam1"
        + ", com.honkentuber.wordwise.GameState stateParam2"
        + ", com.honkentuber.wordwise.GameState stateParam3");
    params = new Object[4];
    params[0] = userKey;
    params[1] = GameState.PENDING;
    params[2] = GameState.PLAYER_TURN;
    params[3] = GameState.OPPONENT_TURN;
    query.setFilter("(memberKeys == userKeyParam)"
        + " && ((state == stateParam1)"
        + " || (state == stateParam2)"
        + " || (state == stateParam3))");

    List<GameDataV2> gamesData = (List<GameDataV2>)
query.executeWithArray(params);

I have the following 2 indexes defined:
  memberKeys ▲ , state ▲ , memberLastAccessMs ▲
  memberKeys ▲ , state ▲ , memberScores ▼

I'm not sure why I don't have an index with only memberKeys and state
- does datastore-indexes autoGenerate not generate a new index if it
already has a superset index?

I've changed the query to the following in my local development
environment:

    Query query = pm.newQuery(GameDataV2.class);
    query.setFilter("(memberKeys == :userKeyParam)
&& :statesParam.contains(state)");
    List<GameDataV2> gamesData = (List<GameDataV2>) query.execute(
        userKey,
        Arrays.asList(
            GameState.PENDING.name(),
            GameState.PLAYER_TURN.name(),
            GameState.OPPONENT_TURN.name()));

Some questions about this:

1) Running locally with autoGenerate="true", I'm not getting a new
GameDataV2 index on memberKeys and states. Does contains() not require
an index on that field? Is this just generating 2 separate queries
internally?
2) Is the contains() query more efficient than the nested ORs I had in
my original query? Or will I still get the "not efficient enough for
this query and your data" error?
3) Why do enumerated types not work with contains()? I had to
add .name() to each entry in the list to get this to work.
4) Why do declared parameters not work with collections? I tried
declaring statesParam as a both List<GameState> and List, and I got
errors resolving the types.

com.google.appengine.api.datastore.DatastoreNeedIndexException: The
built-in indices are not efficient enough for this query and your
data. Please add a composite index for this query..  An index is
missing but we are unable to tell you which one due to a bug in the
App Engine SDK.  If your query only contains equality filters you most
likely need a composite index on all the properties referenced in
those filters.
        at
com.google.appengine.api.datastore.DatastoreApiHelper.translateError(DatastoreApiHelper.java:
40)
        at
com.google.appengine.api.datastore.DatastoreApiHelper.makeSyncCall(DatastoreApiHelper.java:
67)
        at
com.google.appengine.api.datastore.PreparedQueryImpl.runQuery(PreparedQueryImpl.java:
127)
        at
com.google.appengine.api.datastore.PreparedQueryImpl.asIterator(PreparedQueryImpl.java:
87)
        at com.google.appengine.api.datastore.PreparedMultiQuery
$DedupingMultiQueryIterator.getNextIterator(PreparedMultiQuery.java:
154)
        at com.google.appengine.api.datastore.PreparedMultiQuery
$DedupingMultiQueryIterator.computeNext(PreparedMultiQuery.java:173)
        at com.google.appengine.api.datastore.PreparedMultiQuery
$DedupingMultiQueryIterator.computeNext(PreparedMultiQuery.java:98)
        at
com.google.appengine.api.datastore.AbstractIterator.tryToComputeNext(AbstractIterator.java:
52)
        at
com.google.appengine.api.datastore.AbstractIterator.hasNext(AbstractIterator.java:
47)
        at com.google.appengine.api.datastore.BasePreparedQuery
$UncompilablePreparedQuery$1.hasNext(BasePreparedQuery.java:78)
        at
org.datanucleus.store.appengine.query.RuntimeExceptionWrappingIterator.hasNext(RuntimeExceptionWrappingIterator.java:
44)
        at
org.datanucleus.store.appengine.query.LazyResult.resolveAll(LazyResult.java:
115)
        at
org.datanucleus.store.appengine.query.LazyResult.size(LazyResult.java:
110)
        at
org.datanucleus.store.appengine.query.StreamingQueryResult.size(StreamingQueryResult.java:
124)
        at
org.datanucleus.store.query.AbstractQueryResult.toArray(AbstractQueryResult.java:
399)
        at java.util.ArrayList.addAll(Unknown Source)

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to