Malo rendimiento de SQLite en almacenamiento externo en Android
Estoy utilizando el almacenamiento externo para almacenar eventos en una base de datos mientras están esperando para ser enviados al servidor.
Estoy viendo realmente mal rendimiento al insertar registros. Sé que la memoria externa puede ser lenta, pero quería ver algunos números, así que escribí una pequeña aplicación que las pruebas.
- Limitación del número de filas en SQLite
- SQL eliminar de una tabla + un jointable?
- La base de datos Sqlite debe crearse una sola vez
- Sqlite android extraer contactos con número de teléfono
- ¿Es posible simular el cursor sqlite3 en Android cuando no existe db o tabla?
Aquí está el código:
public static final int INSERTS = 100; File dbFile = new File(Environment.getExternalStorageDirectory(), "test.sqlite3"); // File dbFile = new File(getFilesDir(), "test.sqlite3"); dbFile.delete(); SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbFile, null); db.execSQL("CREATE TABLE events (_id integer primary key autoincrement, event_type TEXT NOT NULL, timestamp BIGINT, data TEXT);"); db.execSQL("CREATE INDEX mainIndex ON events (event_type, timestamp ASC);"); InsertHelper helper = new InsertHelper(db, "events"); final int eventTypeCol = helper.getColumnIndex("event_type"); final int timestampCol = helper.getColumnIndex("timestamp"); final int dataCol = helper.getColumnIndex("data"); long start = System.currentTimeMillis(); String eventType = "foo", data = "bar"; long timestamp = 4711; for(int i = 0; i < INSERTS; ++i) { helper.prepareForInsert(); helper.bind(eventTypeCol, eventType); helper.bind(timestampCol, timestamp); helper.bind(dataCol, data); helper.execute(); } long end = System.currentTimeMillis(); Log.i("Test", String.format("InsertHelper, Speed: %d ms, Records per second: %.2f", (int)(end-start), 1000*(double)INSERTS/(double)(end-start))); db.close(); dbFile.delete(); db = SQLiteDatabase.openOrCreateDatabase(dbFile, null); db.execSQL("CREATE TABLE events (_id integer primary key autoincrement, event_type TEXT NOT NULL, timestamp BIGINT, data TEXT);"); db.execSQL("CREATE INDEX mainIndex ON events (event_type, timestamp ASC);"); start = System.currentTimeMillis(); ContentValues cv = new ContentValues(); for(int i = 0; i < INSERTS; ++i) { cv.put("event_type", eventType); cv.put("timestamp", timestamp); cv.put("data", data); db.insert("events", null, cv); } end = System.currentTimeMillis(); Log.i("Test", String.format("Normal, Speed: %d ms, Records per second: %.2f", end-start, 1000*(double)INSERTS/(double)(end-start))); db.close(); dbFile.delete();
La base de datos es exactamente como el que mi aplicación real está utilizando, he intentado eliminar el índice, pero no hizo ninguna diferencia.
Aquí están los resultados:
Nexus One, Memoria interna Método | Registros | Tiempo (ms) | Registros por segundo Unesdoc.unesco.org unesdoc.unesco.org ------ Normal | 100 | 2072 | 48,26 InsertHelper | 100 | 1662 | 60,17 Nexus One, Memoria externa: Método | Registros | Tiempo (ms) | Registros por segundo Unesdoc.unesco.org unesdoc.unesco.org ------ Normal | 100 | 7390 | 13,53 InsertHelper | 100 | 7152 | 13,98 Emulador, Memoria interna: Método | Registros | Tiempo (ms) | Registros por segundo Unesdoc.unesco.org unesdoc.unesco.org ------ Normal | 100 | 1803 | 55,46 InsertHelper | 100 | 3075 | 32,52 Emulador, Memoria externa: Método | Registros | Tiempo (ms) | Registros por segundo Unesdoc.unesco.org unesdoc.unesco.org ------ Normal | 100 | 5742 | 17,42 InsertHelper | 100 | 7164 | 13,96
Como se puede ver el emulador no se puede confiar, InsertHelper
debería ser más rápido si algo.
Esto es, por supuesto, que cabe esperar, la prueba se realizó sobre todo por curiosidad.
Lo que me preocupa sin embargo es el mal desempeño en mi teléfono cuando se utiliza la memoria externa, he perdido algún aspecto crucial de SQLiteDatabase
o es simplemente para que la tarjeta SD será lento?
Puedo añadir que en mi aplicación real he desactivado el bloqueo y hace poca diferencia.
- java.lang.NullPointerException error en una consulta
- ABORTO: HEAP MEMORY CORRUPTION en NDK env. (Biblioteca POCO, Sqlite3, Cocos2dx)
- Android SQLite Eliminar problema de fila
- Actualizar archivo apk en Google Play
- ¿Hay alguna manera eficiente de hacer la consulta de base de datos Android más rápido?
- ¿Cómo puedo buscar los datos de mes específico de la base de datos SQLite
- Crear una restricción única en el conflicto reemplazar
- ¿Rellenar la base de datos de Android desde el archivo CSV?
CommonsWare es correcto en su comentario. Algo que hace una gran diferencia para el rendimiento de db es el uso de transacciones. Envuelva su bucle de inserción en una transacción. No estoy 100% seguro si trabajaría con el InsertHelper pero usted puede intentar substituir su para el lazo con esto:
db.beginTransaction(); try { for(int i = 0; i < INSERTS; ++i) { helper.prepareForInsert(); helper.bind(eventTypeCol, eventType); helper.bind(timestampCol, timestamp); helper.bind(dataCol, data); helper.execute(); } db.setTransactionSuccessful(); } finally { db.endTransaction(); }
Tengo algunos problemas de rendimiento db por lo que utiliza su código para medir los insertos por segundo en mi sistema. Pero también agregué wrapping en {begin, end} Transaction ().
En el emulador. Tengo:
InsertHelper-Internal-Trans, Speed: 67 ms, Records per second: 1492.54 InsertHelper-External-Trans, Speed: 70 ms, Records per second: 1428.57 Normal-Internal-Trans, Speed: 148 ms, Records per second: 675.68 Normal-External-Trans, Speed: 152 ms, Records per second: 657.89 InsertHelper-Internal-NoTrans, Speed: 514 ms, Records per second: 194.55 Normal-Internal-NoTrans, Speed: 519 ms, Records per second: 192.68 InsertHelper-External-NoTrans, Speed: 590 ms, Records per second: 169.49 Normal-External-NoTrans, Speed: 618 ms, Records per second: 161.81
Y en un Samsung Galaxy Nota:
InsertHelper-External-Trans, Speed: 52 ms, Records per second: 1923.08 InsertHelper-Internal-Trans, Speed: 52 ms, Records per second: 1923.08 Normal-External-Trans, Speed: 77 ms, Records per second: 1298.70 Normal-Internal-Trans, Speed: 121 ms, Records per second: 826.45 Normal-External-NoTrans, Speed: 4562 ms, Records per second: 21.92 Normal-Internal-NoTrans, Speed: 4855 ms, Records per second: 20.60 InsertHelper-External-NoTrans, Speed: 5997 ms, Records per second: 16.68 InsertHelper-Internal-NoTrans, Speed: 8361 ms, Records per second: 11.96
- ¿Cómo saber el uso del archivo .apk al almacén de claves para firmar?
- ¿Tengo que usar _ID como una clave primaria de SQlite? Y tiene que ser un INT? (Android Dev)