要回答你的問題(和我的方式),我做了一些測試。
這次試驗主要檢查多少時間查詢了那些兩種情況:
- 使用
cursor.getString(cursor.getColumnIndex(COLUMN_NAME))
方法
- 第一獲取列ID,然後直接調用
cursor.getString(COLUMN_POSITION)
方法
爲了使性能測試具有實際意義,我在數據庫中插入了行,然後我做了一個查詢,投擲我的ContentProvider
這些元素。
結果:
___________________________________________________________________________
| 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% |
|___________________________________________________________________________|
因此,首先讓列ID和呼叫直接getString()
方法將花費大約20%更少的時間。
試驗方法的細節:
平臺:在Android 4.3 的Nexus 7(2012)
數據庫創建:
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());
測試用例:
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");
}
}
我認爲200到500之間的性能下降來自光標窗口。我有很多像200列以上的日誌:
W/CursorWindow(1628): Window is full: requested allocation 2412 bytes, free space 988 bytes, window size 2097152 bytes
我知道,我的問題是:「顯着」更快? – Sergio 2012-02-02 14:41:34
我不知道確切的數字,但我認爲只有當你在桌上有100k +列時,差異才會顯着。確定這一點的最好方法是創建一個示例項目並使用'System.nanoTime()'計算時差。' – 2012-02-02 14:51:02
這與Android有關。通過ContentProvider返回的遊標不需要由SQLite支持。事實上,很多人都沒有。你可以看看遊標的實現以找出你自己。在AbstractCursor.getColumnIndex的快看,你絕對要緩存,如果你有比只是一對夫婦的列更多的索引值自己(的尋找操作是O(n),其中n是列數)。 – lilbyrdie 2014-04-07 12:56:11