2010-10-25 12 views
10

Tenemos unos 7-8 mesas en nuestra aplicación Android que tienen cada uno alrededor de 8 columnas en promedio. Las operaciones de lectura y escritura se realizan en la base de datos y estoy experimentando e intentando encontrar formas de mejorar el rendimiento de la capa de DataAccess. Por lo tanto, ahora he probado los siguientes:Optimización SQLite para la aplicación Android

  1. Use argumentos posicionales en donde las cláusulas (Razón: para que SQLite hace uso del mismo plan de ejecución)
  2. Encierre insertos y actualización con las transacciones (Razón: cada operación db . está encerrado dentro de una transacción por defecto al hacerlo se eliminará esa sobrecarga)
  3. indexación: no he creado ningún índice explícita que no sean los creados por defecto en las columnas de clave primaria y claves únicas (Razón:. indexación mejorará el tiempo de búsqueda)

tengo m enunció mis suposiciones en paranthesis; Por favor, corríjame si estoy equivocado.

Preguntas:

  1. puedo añadir nada más a esta lista? Leí en alguna parte que evitar el uso de db-journal puede mejorar el rendimiento de las actualizaciones. ¿Es esto un mito o un hecho? ¿Cómo se puede hacer esto, si se recomienda?

  2. son transacciones permitidas en SQLite3 agrupar? ¿Cómo afectan el rendimiento? La cosa es que tengo una función que se ejecuta una actualización en un bucle, por lo que, he cerrado el bucle dentro de un bloque de transacción. A veces, esta función se llama desde otro bucle dentro de alguna otra función. La función de llamada también encierra el bucle dentro de un bloque de transacción. ¿Cómo afecta el anidamiento de las transacciones el rendimiento?

  3. El cláusulas donde en mis consultas utilizan más de uno columnas para construir el predicado. Estas columnas pueden no necesariamente por una clave principal o columnas únicas. ¿Debo crear índices en estas columnas también? ¿Es una buena idea crear múltiples índices para dicha tabla?

Respuesta

12
  1. precisar con exactitud qué consultas que necesita para optimizar. Tome una copia de una base de datos típica y use el REPL para consultar el tiempo. Use esto para comparar cualquier ganancia a medida que optimiza.

  2. Use para permitir que el planificador de consultas de SQLite funcione de manera más eficiente.

  3. Para SELECT sy UPDATE s, los índices pueden mejorar, pero solo si los índices que crea pueden ser utilizados por las consultas que necesita acelerar.Use EXPLAIN QUERY PLAN en sus consultas para ver qué índice se usará o si la consulta requiere un escaneo completo de la tabla. Para tablas grandes, una exploración de tabla completa es mala y probablemente desee un índice. Solo se usará un índice en cualquier consulta dada. Si tiene múltiples predicados, entonces el índice que se utilizará es el que se espera que reduzca más el conjunto de resultados (basado en ANALYZE). Puede tener índices que contengan varias columnas (para ayudar a las consultas con múltiples predicados). Si tiene índices con varias columnas, solo se pueden usar si los predicados se ajustan al índice de izquierda a derecha sin espacios (pero las columnas no utilizadas al final están bien). Si usa un predicado de ordenamiento (<, <=, >, etc.), debe estar en la última columna del índice utilizada. El uso de ambos predicados WHERE y ORDER BY requiere un índice y SQLite solo puede usar uno, por lo que puede ser un punto donde el rendimiento se resiente. Cuantos más índices tenga, más lento será su INSERT s, por lo que tendrá que encontrar la mejor solución para su situación.

  4. Si tiene consultas más complejas que no pueden hacer uso de ningún índice que pueda crear, puede desnormalizar su esquema, estructurando sus datos de tal forma que las consultas sean más simples y puedan responderse usando índices

  5. Si está haciendo una gran cantidad de INSERT s, intente soltar índices y recrearlos al final. Necesitará comparar esto.

  6. SQLite does support nested transactions usando puntos de rescate, pero no estoy seguro de que ganes nada ahí en cuanto a rendimiento.

  7. Puede gain lots of speed by compromising on data integrity. Si puede recuperarse de la corrupción de la base de datos usted mismo, entonces esto podría funcionar para usted. Quizás solo puedas hacer esto cuando estés haciendo operaciones intensivas de las que puedas recuperar manualmente.

No estoy seguro de cuánto de esto se puede obtener desde una aplicación de Android. Hay un more detailed guide para optimizar SQLite en general en la documentación de SQLite.

+0

Gracias por tomarse el tiempo para responder a esta pregunta. – Samuh

1

yo añadiría los siguientes:

  1. El uso de rawQuery() en lugar de construir utilizando ContentValues ​​se fije en ciertos casos. por supuesto, es un poco tedioso escribir consultas crudas.

  2. Si tiene una gran cantidad de datos de tipo cadena/texto, considere crear tablas virtuales utilizando la búsqueda de texto completo (FTS3), que puede ejecutar una consulta más rápida. puedes buscar en Google las mejoras de velocidad exactas.

8

Aquí hay un poco de código para obtener EXPLAIN QUERY PLAN resultados en el logcat de Android desde una aplicación de Android en ejecución. Estoy comenzando con SQLiteOpenHelper dbHelper y SQLiteQueryBuilder qb.

String sql = qb.buildQuery(projection,selection,selectionArgs,groupBy,having,sortOrder,limit); 
android.util.Log.d("EXPLAIN",sql + "; " + java.util.Arrays.toString(selectionArgs)); 
Cursor c = dbHelper.getReadableDatabase().rawQuery("EXPLAIN QUERY PLAN " + sql,selectionArgs); 
if(c.moveToFirst()) { 
    do { 
     StringBuilder sb = new StringBuilder(); 
     for(int i = 0; i < c.getColumnCount(); i++) { 
      sb.append(c.getColumnName(i)).append(":").append(c.getString(i)).append(", "); 
     } 
     android.util.Log.d("EXPLAIN",sb.toString()); 
    } while(c.moveToNext()); 
} 
c.close(); 

me cayó esto en mi ContentProvider.query() y ahora se puede ver exactamente cómo se están llevan a cabo todas las consultas. (En mi caso parece que el problema es demasiadas consultas en lugar de un mal uso de la indexación, pero tal vez esto ayude a alguien más ...)

0

un punto menor a añadir a la respuesta de otra manera integral de Robie: la VFS en SQLite (que principalmente está relacionado con el bloqueo) puede intercambiarse por alternativas. Usted puede encontrará una de las alternativas como Unix se suma el o Unix ninguno a ser más rápido, pero prestar atención a las advertencias de la SQLite VFS page!

Normalization (de estructuras de tabla) también vale la pena considerar (si no lo ha hecho ya) simplemente porque tiende a proporcionar la representación más pequeña de los datos en la base de datos; esto es una compensación, menos E/S para más CPU, y una que por lo general vale la pena en las bases de datos empresariales de mediana escala (del tipo con el que estoy más familiarizado), pero me temo que no tengo ni idea de si trade-off funciona bien en plataformas de pequeña escala como Android.