Para responder a su pregunta (y la mía por cierto), hice algunas pruebas.
Esta prueba fue básicamente para comprobar cuánto tiempo la consulta tuvo por esos dos casos:
- Utilizando el
cursor.getString(cursor.getColumnIndex(COLUMN_NAME))
método
- Obtener el ID de columna primero y luego llamar directamente a la
cursor.getString(COLUMN_POSITION)
método
Para hacer que la prueba de rendimiento sea significativa, he insertado líneas en una base de datos y luego hice una consulta arrojé mi ContentProvider
en esos elementos.
Resultados:
___________________________________________________________________________
| Column count| Time (ms) getColumnIndex | Time (ms) columnId | improvement |
|_____________|__________________________|____________________|_____________|
| 500 | 34564 | 30401 | 13% |
| 200 | 9987 | 8502 | 17% |
| 100 | 4713 | 4004 | 17% |
| 50 | 2400 | 1971 | 21% |
| 20 | 1088 | 915 | 19% |
|___________________________________________________________________________|
lo tanto, obtener el ID de la primera columna y la llamada directamente el método getString()
tomará alrededor de 20% menos tiempo.
detalles Método de ensayo:
Plataforma: Nexus 7 (2012) en Android 4.3
creación de bases de datos:
public static int TESTSPEEDCOLUMNCOUNT = 200;
StringBuilder sb = new StringBuilder();
sb.append("CREATE TABLE " + Tables.TESTSPEED + " (");
sb.append(BaseColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT, ");
for (int i = 0; i < (TESTSPEEDCOLUMNCOUNT - 1); ++i) {
sb.append("C" + i + " TEXT, ");
}
sb.append("C" + (TESTSPEEDCOLUMNCOUNT - 1) + " TEXT)");
db.execSQL(sb.toString());
TestCase:
public class ProviderTestSpeed extends ProviderTestCase2<MyProvider> {
private ContentValues createElementForId(String id) {
ContentValues cv = new ContentValues();
for (int i = 0; i < TESTSPEEDCOLUMNCOUNT; ++i) {
cv.put("C" + i, id);
}
return cv;
}
public void testSpeed() {
Log.d(TAG, "testSpeed start columnCount = " + columnCount);
ArrayList<ContentValues> list = new ArrayList<ContentValues>();
ContentValues[] tabcv = {};
for (int j = 0; j < 10; ++j) {
list.clear();
for (int i = 0; i < 500; ++i) {
ContentValues cv = createElementForId(String.valueOf(i));
list.add(cv);
}
mContentResolver.bulkInsert(TestSpeedCONTENT_URI, list.toArray(tabcv));
}
Log.d(TAG, "testSpeed insertFinished");
Cursor cursor = mContentResolver.query(TestSpeedCONTENT_URI, null, null, null, null);
cursor.moveToFirst();
Log.d(TAG, "testSpeed itemCount = " + cursor.getCount() + " columnCount=" + cursor.getColumnCount());
// build the tab to avoid dynamic allocation during the mesure
ArrayList<String> listColumns = new ArrayList<String>();
for (int i = 0; i < TESTSPEEDCOLUMNCOUNT; ++i) {
listColumns.add("C" + i);
}
String[] tabColumnsType = {};
String[] tabColumns = listColumns.toArray(tabColumnsType);
Date now = new Date();
long start = now.getTime();
do {
for (int i = 0; i < TESTSPEEDCOLUMNCOUNT; ++i) {
// get the all the columns of the table
cursor.getString(cursor.getColumnIndex(tabColumns[i]));
}
} while (cursor.moveToNext());
now = new Date();
long end = now.getTime();
Log.d(TAG, "testSpeed took " + (end - start) + " with getColumnIndex at each time");
cursor.moveToFirst();
now = new Date();
start = now.getTime();
do {
for (int i = 0; i < TESTSPEEDCOLUMNCOUNT; ++i) {
// get the all the columns of the table using directly the column id
cursor.getString(i);
}
} while (cursor.moveToNext());
now = new Date();
end = now.getTime();
Log.d(TAG, "testSpeed took " + (end - start) + " with getColumnIndex before loop");
}
}
Creo que la caída de rendimiento entre 200 y 500 proviene de la ventana del cursor. Tenía muchos registros como esos por encima de 200 columnas:
W/CursorWindow(1628): Window is full: requested allocation 2412 bytes, free space 988 bytes, window size 2097152 bytes
Lo sé, mi pregunta es: "significativamente" más rápido? – Sergio
no sé el número exacto, pero creo que la diferencia será significativa solo si tiene 100k + columnas en una tabla. La mejor manera de determinar esto es crear un proyecto de muestra y calcular la diferencia de tiempo usando 'System.nanoTime()' –
Esto pertenece a Android. Un Cursor devuelto a través de ContentProvider no requiere que esté respaldado por SQLite.De hecho, muchos no lo son. Puede ver las implementaciones de los cursores para descubrirlo usted mismo. En una vista rápida de AbstractCursor.getColumnIndex, querrá guardar en caché los valores de índice si tiene más de un par de columnas (la búsqueda es O (n) donde n es el número de columnas). – lilbyrdie