Aby odpowiedzieć na twoje pytanie (i moje przy okazji), zrobiłem kilka testów.
Test ten był w zasadzie do sprawdzenia, ile czasu kwerendy zabrał tych dwóch przypadkach:
- Stosując metodę
- Uzyskiwanie identyfikatora kolumny, a następnie wywołanie bezpośrednio metodę
cursor.getString(COLUMN_POSITION)
cursor.getString(cursor.getColumnIndex(COLUMN_NAME))
Aby test wydajności był znaczący, wstawiłem linie w bazie danych, a następnie wysłałem zapytanie: ContentProvider
w sprawie tych elementów.
Wyniki:
___________________________________________________________________________
| 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% |
|___________________________________________________________________________|
Więc coraz id kolumny pierwszej i wywołanie bezpośrednio metodę getString()
zajmie około 20% mniej czasu.
szczegóły metody badawczej:
Platforma: Nexus 7 (2012) na Androidzie 4.3
stworzenie bazy danych:
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");
}
}
Myślę, że spadek wydajności od 200 do 500 pochodzi z okna kursora. Miałem dużo dzienników takich jak powyżej 200 kolumn:
W/CursorWindow(1628): Window is full: requested allocation 2412 bytes, free space 988 bytes, window size 2097152 bytes
Wiem, że moje pytanie brzmi: "znacząco" szybciej? – Sergio
Nie znam dokładnej liczby, ale myślę, że różnica będzie znacząca tylko wtedy, gdy masz 100k + kolumn w tabeli. Najlepszym sposobem ustalenia tego jest utworzenie przykładowego projektu i obliczenie różnicy czasu za pomocą 'System.nanoTime()' –
Dotyczy to systemu Android. Kursor zwrócony przez ContentProvider nie ma wymogu, aby był on wspierany przez SQLite.W rzeczywistości bardzo wielu nie jest. Możesz przyjrzeć się implementacjom kursorów, aby się przekonać. W szybkim wyglądzie AbstractCursor.getColumnIndex, będziesz absolutnie chciał cachować wartości indeksu samodzielnie, jeśli masz więcej niż kilka kolumn (wyszukiwanie to O (n) gdzie n jest liczbą kolumn). – lilbyrdie