2011-08-26 7 views
10

Im ejecutar una consulta y actualmente se está volviendo 1400 resultados y debido a esto que estoy recibiendo la siguiente advertencia en el archivo de registro:Para Google App Engine (java), ¿cómo configuro y uso el tamaño de fragmento en FetchOptions?

com.google.appengine.api.datastore.QueryResultsSourceImpl logChunkSizeWarning: esta consulta no tiene un tamaño de fragmento establecido en FetchOptions y ha devuelto más de 1000 resultados. Si los conjuntos de resultados de de este tamaño son comunes para esta consulta, considere establecer un tamaño de fragmento en para mejorar el rendimiento.

No puedo encontrar ningún ejemplo de cómo implementar esto realmente, aquí hay una pregunta sobre python, pero como estoy usando Java y no entiendo Python, me cuesta traducirlo.

También esta consulta (abajo) está ejecutando 17226cpu_ms, que se siente como demasiado tiempo, ni siquiera puedo imaginar qué pasaría si dijera 5000 contactos y necesitara buscarlos en el lado del cliente (como lo hace ! con contactos Googlemail)

El código que tengo es:

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); 

me encontré con los siguientes dos entradas de aquí:

pero tampoco entra realmente ningún detalle acerca de cómo implementar o usar estas opciones. Supongo que es un proceso del lado del servidor, y supongo que está destinado a configurar algún tipo de bucle para tomar los pedazos un trozo a la vez, pero ¿cómo puedo hacer eso?

  • ¿Llamo la consulta dentro de un bucle?
  • ¿Cómo sé cuántas veces para hacer un bucle?
  • ¿Acabo de verificar el primer fragmento que se devuelve con un número de entradas inferior al tamaño del fragmento?

¿Cómo voy a tratar de descubrir cosas como esta sin un ejemplo real a seguir? Me parece que otras personas aquí parecen "solo saber" cómo hacerlo ...!

Lo siento si no estoy haciendo las preguntas de la manera correcta o simplemente soy un novato oscuro sobre esto, pero no sé a dónde más recurrir para resolver esto!

Respuesta

4

Enfrentando el mismo problema y el último comentario fue de hace un mes, así que aquí está lo que descubrí sobre la consulta pesada de conjunto de datos.

supongo que voy a utilizar la técnica de "cursor de consulta" después de leer estas líneas en los documentos de Google article (el de pitón mencionado por cierto):

Este artículo fue escrito para la versión SDK 1.1.7. A partir de la versión 1.3.1, cursores de consulta (Java | Python) han reemplazado las técnicas descritas a continuación y ahora son el método recomendado para buscar grandes conjuntos de datos .

En los documentos de google sobre "Query Cursor". La primera línea del documento da precisamente la razón por la necesidad de cursor:

cursores de consulta permiten una aplicación para realizar una consulta y recuperar un lote de resultados, a continuación, extraer resultados adicionales para la misma consulta en una solicitud web posterior sin la sobrecarga de un desplazamiento de consulta.

La documentación proporciona también un ejemplo java de un servlet utilizando la técnica de cursor. Hay un consejo sobre cómo generar un cursor seguro para el cliente. Finalmente, se exponen las limitaciones del cursor .

Espero que esto le da una pista para resolver su problema.

Pequeño recordatorio de gama y compensados ​​, bastante impactar en el rendimiento en caso de olvido (y lo hice ^^):

El desplazamiento inicial tiene implicaciones para la prestación del servicio: el almacén de datos debe recuperar y luego desechar todo resultados antes del inicio offset. Por ejemplo, una consulta con un rango de 5, 10 obtiene diez resultados desde el almacén de datos, luego descarta los cinco primeros y devuelve el restante a la aplicación.


Edit: Como trabajar con JDO, Seguí buscando una manera de permitir que mi código anterior para cargar más de 1.000 resultan en una sola consulta. Por lo tanto, si usted está utilizando JDO también, me encontré con este viejo issue:

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

Así es como me aplico FetchOptions, en comparación con el código de ejemplo, es posible que tenga que modificar un poco:

// ..... 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); 

Por supuesto que las cifras pueden ser cambiados (100).

Si mi respuesta no es la que está buscando, puede reformular su pregunta (editar).

Por cierto, soy yo quien escribió la primera pregunta vinculada.

+0

No estoy seguro de cómo reformular mi pregunta, así que solo voy a responder a su comentario. ¿Debo sustituir simplemente mi línea de código: "List Contacts = (List ) query.execute (AdminID);" con tus dos líneas de código? Si es así, ¿puedes ayudarme cambiando tu código para que coincida con las variables en el mío?como no puedo resolverlo. Probé alrededor de 20 combinaciones de mis variables, pero nada tiene sentido, y es por eso que formulé las preguntas anteriores ... Una cosa que he golpeado un par de veces parece estar relacionada con el hecho de que mi "Consulta" "arriba se importa como" javax.jdo.Query; " – johnvdenley

+0

¿Alguien puede ayudarme con esto ya que ahora me está causando un problema? Ya no puedo solucionarlo. – johnvdenley

1

Si está utilizando el almacén de datos directamente, sin JDO, entonces usted podría hacer algo como lo siguiente para configurar el tamaño de porción cuando está iterando a través de los datos:

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)) { 
    ... 
} 
+0

Odio decirlo, pero nunca resolví cómo hacer esto, acabo de llamar a un cliente para decir que este problema ha levantado su horrible cabeza otra vez ... Están reuniendo 2044 registros de datos del motor de la aplicación y obtengo el error de nuevo para establecer el tamaño del fragmento para evitar el problema ... Básicamente estoy recibiendo un tiempo de espera sobre la carga de datos y todavía no entiendo cómo resolver el problema, para mí es el bit "..." en tu ciclo for arriba que no sé cómo manejar. ¿El almacén de datos devolverá los resultados en 200 fragmentos? ¿Los recombinaré antes de enviarlos al cliente? – johnvdenley

+0

Sí, los recombinaría @johnvdenley. Está dividiendo la consulta para que termine más rápido y luego combine los resultados para igualar la lista completa. – Gray