2011-09-16 46 views
6

Estoy usando una base de datos SQLite en una aplicación de Android y el método getAll que he escrito toma demasiado tiempo en mi opinión.Looping a través de un cursor SQLite toma demasiado tiempo

Este es el código que estoy hablando:

public static List<Feed> getAll(Context context) { 
     List<Feed> feeds = new ArrayList<Feed>(); 
     Uri allFeeds = Uri.parse(ContentProvidersUris.URL_CONTENT_PROVIDER_FEED); 

     long startQuery = BenchmarkUtils.start(); 
     Cursor c = context.getContentResolver().query(allFeeds, null, null, null, "title desc"); 

     long startCursor = BenchmarkUtils.start(); 
     for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { 
      long startInsideCursor = BenchmarkUtils.start(); 

      Feed feed = new Feed(); 
      feed.setContent(c.getString(c.getColumnIndex(FeedsProvider.COL_WEBVIEW_CONTENT))); 
      feed.setDate(c.getString(c.getColumnIndex(FeedsProvider.COL_PUB_DATE))); 
      feed.setDescription(c.getString(c.getColumnIndex(FeedsProvider.COL_DESCRIPTION))); 
      feed.setName(c.getString(c.getColumnIndex(FeedsProvider.COL_FEED_NAME))); 

      Log.d(TAG, "This loop cursor iteration took : " + BenchmarkUtils.stop(startInsideCursor) + " ms."); 
     } 

     Log.d(TAG, "Looping through the ENTIRE Cursor took: " + BenchmarkUtils.stop(startCursor) + " ms."); 


     return feeds; 
} 

Como se puede ver también estoy midiendo el tiempo empleado por este bucle en cada iteración y resulta que se necesita un tiempo promedio de 1800 ms (en un Nexus S). Encuentro que esto es mucho tiempo. Y lo que no entiendo es que la mayor parte de este tiempo se dedica en la primera iteración como se muestra en los registros:

D/FeedsProviderHelper (5800): Este cursor iteración del bucle tomó: 1726 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 3 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 2 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 3 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 2 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 3 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 3 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 2 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 0 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 5 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 1 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 1 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 5 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 1 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 1 ms.

D/FeedsProviderHelper (5800): Esta iteración del cursor de bucle tomó: 1 ms.

D/FeedsProviderHelper (5800): Looping a través del Cursor TOTAL tomó: 1770 ms.

Así que mis preguntas son:

¿Es normal? ¿Si es así por qué? Si no, ¿qué estoy haciendo mal? ¿Alguna forma más rápida de hacer un selectAll contra la base de datos SQLite?

Gracias!

EDITAR

Tomé las getColumnIndex llamadas fuera del circuito como @superfell sugirió, y ahora estoy ejecutando el método getAll en un promedio 1.500 ms. ¡Es más rápido pero no lo suficientemente rápido en mi opinión (de nuevo)!

+0

Si el proveedor de contenido está en el mismo proceso, o se está procesando de manera cruzada, el tiempo en esa primera fila parece muy extraño. – superfell

+0

@superfell Mismo proceso. –

Respuesta

3

¿Es normal?

Sure.

En caso afirmativo, ¿por qué?

La E/S de disco es costosa, especialmente en flash. La consulta en sí se está ejecutando en su primera solicitud real en contra de Cursor, por lo que su primera "iteración" tarda mucho más.

¿Alguna manera más rápida de hacer una selecciónTodo contra la base de datos SQLite?

En primer lugar, no está haciendo un "selectAll" contra una base de datos SQLite. Estás haciendo un "selectAll" contra un proveedor de contenido.

Utilice Traceview para determinar con precisión dónde se está dedicando su tiempo, y ajuste su aplicación en consecuencia. Por ejemplo, es posible que tenga más sentido no copiar datos de Cursor en una lista de POJO en primer lugar.

+0

¡Gracias, ahora está más claro! Dado que estás hablando de Traceview, ¿puedes echarle un vistazo a esta pregunta, por favor? http://stackoverflow.com/questions/6491855/android-cant-use-traceview Simplemente no pude usarlo :( –

+0

@CommonsWare ¿Cuál sería su recomendación? ¿Qué hacer copiando los datos a la lista de POJO cuando hacer consultas crudas? Gracias – Ewoks

+0

@Ewoks: la alternativa es trabajar directamente con el 'Cursor' (por ejemplo, ponerlo en' SimpleCursorAdapter'). – CommonsWare

9

Lo primero que debe hacer es sacar las llamadas getColumnIndex del ciclo, son caras, y solo tiene que hacerlas una vez, no para cada fila.

+0

Buen punto. Haré esto. –

+0

Me salvó ~ 300ms. –

Cuestiones relacionadas